moving code around for a better file structure
This commit is contained in:
parent
8f3e898385
commit
7eba697dc2
27 changed files with 20 additions and 24 deletions
187
src/cpp/filemanager.cpp
Normal file
187
src/cpp/filemanager.cpp
Normal file
|
@ -0,0 +1,187 @@
|
|||
#include "filemanager.h"
|
||||
#include <ktar.h>
|
||||
#include <KCompressionDevice>
|
||||
#include <KArchiveDirectory>
|
||||
#include <KArchiveFile>
|
||||
#include <KArchiveEntry>
|
||||
#include <QDebug>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QFile>
|
||||
#include <QTemporaryFile>
|
||||
#include <QDir>
|
||||
|
||||
File::File(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
qDebug() << "Initializing empty file";
|
||||
}
|
||||
|
||||
File::File(const QString &name, const QString &filePath, QObject *parent)
|
||||
: QObject(parent),m_name(name),m_filePath(filePath)
|
||||
{
|
||||
qDebug() << "Initializing file with defaults";
|
||||
}
|
||||
|
||||
QString File::name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
QString File::filePath() const {
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
void File::setName(QString name)
|
||||
{
|
||||
if (m_name == name)
|
||||
return;
|
||||
|
||||
qDebug() << "####changing name to: " << name;
|
||||
m_name = name;
|
||||
emit nameChanged(m_name);
|
||||
}
|
||||
|
||||
void File::setFilePath(QString filePath)
|
||||
{
|
||||
if (m_filePath == filePath)
|
||||
return;
|
||||
|
||||
qDebug() << "####changing filePath to: " << filePath;
|
||||
m_filePath = filePath;
|
||||
emit filePathChanged(m_filePath);
|
||||
}
|
||||
|
||||
bool File::save(QUrl file, QVariantList serviceList) {
|
||||
qDebug() << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
|
||||
qDebug() << "Saving...";
|
||||
qDebug() << "File path is: " << file.toString();
|
||||
qDebug() << "serviceList is: " << serviceList;
|
||||
qDebug() << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
|
||||
|
||||
//first we'll get a json representation of our serviceList
|
||||
//save that to a temp file in case we need it but also convert
|
||||
//it to a byte array just before putting it into the archive
|
||||
|
||||
QJsonArray jsonData;
|
||||
|
||||
// save all the audio and files in jsonData as just the base name
|
||||
// so that they are properly mapped in the resulting archive
|
||||
for (int i = 0; i < serviceList.length(); i++) {
|
||||
// qDebug() << serviceList[i];
|
||||
QMap item = serviceList[i].toMap();
|
||||
qDebug() << "AUDIO IS: " << item.value("audio").toString();
|
||||
QFileInfo audioFile = item.value("audio").toString();
|
||||
qDebug() << audioFile.fileName();
|
||||
item["flatAudio"] = audioFile.fileName();
|
||||
qDebug() << "AUDIO IS NOW: " << item.value("audio").toString();
|
||||
|
||||
QFileInfo backgroundFile = item.value("background").toString();
|
||||
item["flatBackground"] = backgroundFile.fileName();
|
||||
qDebug() << "BACKGRUOND IS: " << item.value("background").toString();
|
||||
// qDebug() << serviceList[i].value();
|
||||
QJsonObject obj = QJsonObject::fromVariantMap(item);
|
||||
qDebug() << obj;
|
||||
jsonData.insert(i, obj);
|
||||
}
|
||||
|
||||
qDebug() << jsonData;
|
||||
QJsonDocument jsonText(jsonData);
|
||||
QTemporaryFile jsonFile;
|
||||
|
||||
if (!jsonFile.exists())
|
||||
qDebug() << "NOT EXISTS!";
|
||||
|
||||
if (!jsonFile.open())
|
||||
return false;
|
||||
|
||||
//finalize the temp json file, in case something goes wrong in the
|
||||
//archive, we'll have this to jump back to
|
||||
jsonFile.write(jsonText.toJson());
|
||||
qDebug() << jsonFile.fileName();
|
||||
jsonFile.close();
|
||||
|
||||
//now we create our archive file and set it's parameters
|
||||
QString filename = file.toString().right(file.toString().size() - 7);
|
||||
qDebug() << filename;
|
||||
|
||||
// KCompressionDevice dev(filename, KCompressionDevice::Zstd);
|
||||
// if (!dev.open(QIODevice::WriteOnly)) {
|
||||
// qDebug() << dev.isOpen();
|
||||
// return false;
|
||||
// }
|
||||
KTar tar(filename, "application/zstd");
|
||||
|
||||
if (tar.open(QIODevice::WriteOnly)) {
|
||||
qDebug() << tar.isOpen();
|
||||
|
||||
//write our json data to the archive
|
||||
tar.writeFile("servicelist.json",
|
||||
jsonText.toJson());
|
||||
|
||||
//let's add the backgrounds and audios to the archive
|
||||
for (int i = 0; i < serviceList.size(); i++) {
|
||||
QMap item = serviceList[i].toMap();
|
||||
QString background = item.value("background").toString();
|
||||
QString backgroundFile = background.right(background.size() - 5);
|
||||
qDebug() << backgroundFile;
|
||||
QString audio = item.value("audio").toString();
|
||||
QString audioFile = audio.right(audio.size() - 5);
|
||||
qDebug() << audioFile;
|
||||
|
||||
//here we need to cut off all the directories before
|
||||
//adding into the archive
|
||||
tar.addLocalFile(backgroundFile,
|
||||
backgroundFile.right(backgroundFile.size() -
|
||||
backgroundFile.lastIndexOf("/") - 1));
|
||||
tar.addLocalFile(audioFile,
|
||||
audioFile.right(audioFile.size() -
|
||||
audioFile.lastIndexOf("/") - 1));
|
||||
}
|
||||
|
||||
//close the archive so that everything is done
|
||||
tar.close();
|
||||
// dev.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariantList File::load(QUrl file) {
|
||||
qDebug() << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
|
||||
qDebug() << "Loading...";
|
||||
qDebug() << "File path is: " << file.toString();
|
||||
qDebug() << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
|
||||
|
||||
|
||||
QString fileUrl = file.toString().right(file.toString().size() - 7);
|
||||
KTar tar(fileUrl);
|
||||
|
||||
if (tar.open(QIODevice::ReadOnly)){
|
||||
qDebug() << tar.isOpen();
|
||||
const KArchiveDirectory *dir = tar.directory();
|
||||
|
||||
const KArchiveEntry *e = dir->entry("servicelist.json");
|
||||
if (!e) {
|
||||
qDebug() << "File not found!";
|
||||
}
|
||||
const KArchiveFile *f = static_cast<const KArchiveFile *>(e);
|
||||
QByteArray arr(f->data());
|
||||
QJsonDocument jsonText = QJsonDocument::fromJson(arr);
|
||||
qDebug() << jsonText; // the file contents
|
||||
|
||||
QJsonArray array = jsonText.array();
|
||||
|
||||
QVariantList serviceList = array.toVariantList();
|
||||
qDebug() << serviceList;
|
||||
return serviceList;
|
||||
|
||||
}
|
||||
|
||||
QVariantList blankList;
|
||||
return blankList;
|
||||
|
||||
}
|
40
src/cpp/filemanager.h
Normal file
40
src/cpp/filemanager.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef FILEMANAGER_H
|
||||
#define FILEMANAGER_H
|
||||
|
||||
#include <qobjectdefs.h>
|
||||
#include <qqml.h>
|
||||
#include <QObject>
|
||||
#include <qobject.h>
|
||||
|
||||
|
||||
class File : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
|
||||
Q_PROPERTY(QString filePath READ filePath WRITE setFilePath NOTIFY filePathChanged)
|
||||
// QML_ELEMENT
|
||||
|
||||
public:
|
||||
explicit File(QObject *parent = nullptr);
|
||||
File(const QString &name, const QString &filePath,
|
||||
QObject * parent = nullptr);
|
||||
|
||||
QString name() const;
|
||||
QString filePath() const;
|
||||
|
||||
Q_INVOKABLE void setName(QString name);
|
||||
Q_INVOKABLE void setFilePath(QString filePath);
|
||||
|
||||
Q_INVOKABLE bool save(QUrl file, QVariantList serviceList);
|
||||
Q_INVOKABLE QVariantList load(QUrl file);
|
||||
|
||||
signals:
|
||||
Q_INVOKABLE void nameChanged(QString name);
|
||||
Q_INVOKABLE void filePathChanged(QString filePath);
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
QString m_filePath;
|
||||
};
|
||||
|
||||
#endif //FILEMANAGER_H
|
204
src/cpp/imagesqlmodel.cpp
Normal file
204
src/cpp/imagesqlmodel.cpp
Normal file
|
@ -0,0 +1,204 @@
|
|||
#include "imagesqlmodel.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QSqlError>
|
||||
#include <QSqlRecord>
|
||||
#include <QSqlQuery>
|
||||
#include <QSql>
|
||||
#include <QSqlDatabase>
|
||||
#include <QFileInfo>
|
||||
#include <qabstractitemmodel.h>
|
||||
#include <qdebug.h>
|
||||
#include <qnamespace.h>
|
||||
#include <qobject.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qsqlrecord.h>
|
||||
#include <qurl.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
static const char *imagesTableName = "images";
|
||||
|
||||
static void createImageTable()
|
||||
{
|
||||
if(QSqlDatabase::database().tables().contains(imagesTableName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QSqlQuery query;
|
||||
if (!query.exec("CREATE TABLE IF NOT EXISTS 'images' ("
|
||||
" 'id' INTEGER NOT NULL,"
|
||||
" 'title' TEXT NOT NULL,"
|
||||
" 'filePath' TEXT NOT NULL,"
|
||||
" PRIMARY KEY(id))")) {
|
||||
qFatal("Failed to query database: %s",
|
||||
qPrintable(query.lastError().text()));
|
||||
}
|
||||
qDebug() << query.lastQuery();
|
||||
qDebug() << "inserting into images";
|
||||
|
||||
query.exec("INSERT INTO images (title, filePath) VALUES ('Dec 180', 'file:///home/chris/nextcloud/tfc/openlp/180-dec.png')");
|
||||
qDebug() << query.lastQuery();
|
||||
query.exec("INSERT INTO images (title, filePath) VALUES ('No TFC', "
|
||||
"'file:///home/chris/nextcloud/tfc/openlp/No TFC.png')");
|
||||
|
||||
query.exec("select * from images");
|
||||
qDebug() << query.lastQuery();
|
||||
}
|
||||
|
||||
ImageSqlModel::ImageSqlModel(QObject *parent) : QSqlTableModel(parent) {
|
||||
qDebug() << "creating image table";
|
||||
createImageTable();
|
||||
setTable(imagesTableName);
|
||||
setEditStrategy(QSqlTableModel::OnManualSubmit);
|
||||
// make sure to call select else the model won't fill
|
||||
select();
|
||||
}
|
||||
|
||||
QVariant ImageSqlModel::data(const QModelIndex &index, int role) const {
|
||||
if (role < Qt::UserRole) {
|
||||
return QSqlTableModel::data(index, role);
|
||||
}
|
||||
|
||||
// qDebug() << role;
|
||||
const QSqlRecord sqlRecord = record(index.row());
|
||||
return sqlRecord.value(role - Qt::UserRole);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ImageSqlModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> names;
|
||||
names[Qt::UserRole] = "id";
|
||||
names[Qt::UserRole + 1] = "title";
|
||||
names[Qt::UserRole + 2] = "filePath";
|
||||
return names;
|
||||
}
|
||||
|
||||
void ImageSqlModel::newImage(const QUrl &filePath) {
|
||||
qDebug() << "adding new image";
|
||||
int rows = rowCount();
|
||||
|
||||
qDebug() << rows;
|
||||
QSqlRecord recordData = record();
|
||||
QFileInfo fileInfo = filePath.toString();
|
||||
QString title = fileInfo.baseName();
|
||||
recordData.setValue("title", title);
|
||||
recordData.setValue("filePath", filePath);
|
||||
|
||||
if (insertRecord(rows, recordData)) {
|
||||
submitAll();
|
||||
} else {
|
||||
qDebug() << lastError();
|
||||
};
|
||||
}
|
||||
|
||||
void ImageSqlModel::deleteImage(const int &row) {
|
||||
QSqlRecord recordData = record(row);
|
||||
if (recordData.isEmpty())
|
||||
return;
|
||||
|
||||
removeRow(row);
|
||||
submitAll();
|
||||
}
|
||||
|
||||
int ImageSqlModel::id() const {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString ImageSqlModel::title() const {
|
||||
return m_title;
|
||||
}
|
||||
|
||||
void ImageSqlModel::setTitle(const QString &title) {
|
||||
if (title == m_title)
|
||||
return;
|
||||
|
||||
m_title = title;
|
||||
|
||||
select();
|
||||
emit titleChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the title from outside the delegate
|
||||
void ImageSqlModel::updateTitle(const int &row, const QString &title) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from images");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
// qDebug() << rowdata.value(0);
|
||||
rowdata.setValue("title", title);
|
||||
bool suc = setRecord(id, rowdata);
|
||||
qDebug() << "#############";
|
||||
qDebug() << rowdata.value("title");
|
||||
qDebug() << "was it successful? " << suc;
|
||||
qDebug() << "#############";
|
||||
bool suca = submitAll();
|
||||
// qDebug() << suca;
|
||||
emit titleChanged();
|
||||
}
|
||||
|
||||
QUrl ImageSqlModel::filePath() const {
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
void ImageSqlModel::setFilePath(const QUrl &filePath) {
|
||||
if (filePath == m_filePath)
|
||||
return;
|
||||
|
||||
m_filePath = filePath;
|
||||
|
||||
select();
|
||||
emit filePathChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the filepath from outside the delegate
|
||||
void ImageSqlModel::updateFilePath(const int &row, const QUrl &filePath) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from images");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("filePath", filePath);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit filePathChanged();
|
||||
}
|
||||
|
||||
QVariantMap ImageSqlModel::getImage(const int &row) {
|
||||
// qDebug() << "Row we are getting is " << row;
|
||||
// QUrl image;
|
||||
// QSqlRecord rec = record(row);
|
||||
// qDebug() << rec.value("filePath").toUrl();
|
||||
// // image.append(rec.value("title"));
|
||||
// // image.append(rec.value("filePath"));
|
||||
// image = rec.value("filePath").toUrl();
|
||||
// return image;
|
||||
|
||||
QVariantMap data;
|
||||
const QModelIndex idx = this->index(row,0);
|
||||
// qDebug() << idx;
|
||||
if( !idx.isValid() )
|
||||
return data;
|
||||
const QHash<int,QByteArray> rn = roleNames();
|
||||
// qDebug() << rn;
|
||||
QHashIterator<int,QByteArray> it(rn);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
qDebug() << it.key() << ":" << it.value();
|
||||
data[it.value()] = idx.data(it.key());
|
||||
}
|
||||
return data;
|
||||
}
|
49
src/cpp/imagesqlmodel.h
Normal file
49
src/cpp/imagesqlmodel.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef IMAGESQLMODEL_H
|
||||
#define IMAGESQLMODEL_H
|
||||
|
||||
#include <QSqlTableModel>
|
||||
#include <qobject.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qqml.h>
|
||||
#include <qurl.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
class ImageSqlModel : public QSqlTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int id READ id)
|
||||
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
|
||||
Q_PROPERTY(QUrl filePath READ filePath WRITE setFilePath NOTIFY filePathChanged)
|
||||
QML_ELEMENT
|
||||
|
||||
public:
|
||||
ImageSqlModel(QObject *parent = 0);
|
||||
|
||||
int id() const;
|
||||
QString title() const;
|
||||
QUrl filePath() const;
|
||||
|
||||
void setTitle(const QString &title);
|
||||
void setFilePath(const QUrl &filePath);
|
||||
|
||||
Q_INVOKABLE void updateTitle(const int &row, const QString &title);
|
||||
Q_INVOKABLE void updateFilePath(const int &row, const QUrl &filePath);
|
||||
|
||||
Q_INVOKABLE void newImage(const QUrl &filePath);
|
||||
Q_INVOKABLE void deleteImage(const int &row);
|
||||
Q_INVOKABLE QVariantMap getImage(const int &row);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
signals:
|
||||
void titleChanged();
|
||||
void filePathChanged();
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
QString m_title;
|
||||
QUrl m_filePath;
|
||||
};
|
||||
|
||||
#endif //IMAGESQLMODEL_H
|
159
src/cpp/main.cpp
Normal file
159
src/cpp/main.cpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
#include <QApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QtQml>
|
||||
#include <QUrl>
|
||||
#include <QSql>
|
||||
#include <QDebug>
|
||||
#include <KLocalizedContext>
|
||||
#include <KLocalizedString>
|
||||
#include <KAboutData>
|
||||
#include <iostream>
|
||||
#include <QQmlEngine>
|
||||
#include <QtSql>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlTableModel>
|
||||
|
||||
#include <QObject>
|
||||
#include <QtGlobal>
|
||||
#include <QOpenGLContext>
|
||||
#include <QGuiApplication>
|
||||
#include <QQuickStyle>
|
||||
|
||||
#include <QtGui/QOpenGLFramebufferObject>
|
||||
|
||||
#include <QtQuick/QQuickWindow>
|
||||
#include <QtQuick/QQuickView>
|
||||
#include <qapplication.h>
|
||||
#include <qcoreapplication.h>
|
||||
#include <qdir.h>
|
||||
#include <qglobal.h>
|
||||
#include <qguiapplication.h>
|
||||
#include <qqml.h>
|
||||
#include <qquickstyle.h>
|
||||
#include <qsqldatabase.h>
|
||||
#include <qsqlquery.h>
|
||||
#include <qstringliteral.h>
|
||||
|
||||
#include "mpv/mpvobject.h"
|
||||
#include "serviceitemmodel.h"
|
||||
#include "songsqlmodel.h"
|
||||
#include "videosqlmodel.h"
|
||||
#include "imagesqlmodel.h"
|
||||
#include "presentationsqlmodel.h"
|
||||
#include "filemanager.h"
|
||||
#include "slide.h"
|
||||
|
||||
// RUST
|
||||
#include "cxx-qt-gen/my_object.cxxqt.h"
|
||||
|
||||
static void connectToDatabase() {
|
||||
// let's setup our sql database
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
if (!db.isValid()){
|
||||
db = QSqlDatabase::addDatabase("QSQLITE");
|
||||
if (!db.isValid())
|
||||
qFatal("Cannot add database: %s", qPrintable(db.lastError().text()));
|
||||
}
|
||||
|
||||
const QDir writeDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
qDebug() << "dir location " << writeDir.absolutePath();
|
||||
|
||||
if (!writeDir.mkpath(".")) {
|
||||
qFatal("Failed to create writable location at %s", qPrintable(writeDir.absolutePath()));
|
||||
}
|
||||
|
||||
const QString dbName = writeDir.absolutePath() + "/library-db.sqlite3";
|
||||
|
||||
db.setHostName("localhost");
|
||||
db.setDatabaseName(dbName);
|
||||
db.setUserName("presenter");
|
||||
// TODO change password system before launch
|
||||
db.setPassword("i393jkf782djyr98302j");
|
||||
if (!db.open()) {
|
||||
qFatal("Cannot open database: %s", qPrintable(db.lastError().text()));
|
||||
QFile::remove(dbName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("system-config-display")));
|
||||
QApplication app(argc, argv);
|
||||
KLocalizedString::setApplicationDomain("librepresenter");
|
||||
KAboutData aboutData("librepresenter", i18n("Libre Presenter"), "0.1",
|
||||
i18n("A church presentation app built with KDE tech."),
|
||||
KAboutLicense::GPL_V3,
|
||||
i18n("Copyright 2017 Bar Foundation"), QString(),
|
||||
"https://www.foo-the-app.net");
|
||||
// overwrite default-generated values of organizationDomain & desktopFileName
|
||||
aboutData.setOrganizationDomain("tfcconnection.org");
|
||||
aboutData.setDesktopFileName("org.tfcconnection.librepresenter");
|
||||
|
||||
// set the application metadata
|
||||
KAboutData::setApplicationData(aboutData);
|
||||
QCoreApplication::setOrganizationName(QStringLiteral("librepresenter"));
|
||||
QCoreApplication::setOrganizationDomain(QStringLiteral("tfcconnection.org"));
|
||||
QCoreApplication::setApplicationName(QStringLiteral("Libre Presenter"));
|
||||
qSetMessagePattern("[%{type} %{time h:m:s ap}: %{function} in %{file}]: %{message}\n");
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
QIcon::setFallbackThemeName("breeze");
|
||||
QQuickStyle::setStyle(QStringLiteral("org.kde.breeze"));
|
||||
// QApplication::setStyle(QStringLiteral("breeze"));
|
||||
#else
|
||||
QIcon::setFallbackThemeName("breeze");
|
||||
QQuickStyle::setStyle(QStringLiteral("org.kde.desktop"));
|
||||
QQuickStyle::setFallbackStyle(QStringLiteral("Default"));
|
||||
#endif
|
||||
|
||||
qDebug() << QQuickStyle::availableStyles();
|
||||
qDebug() << QIcon::themeName();
|
||||
|
||||
// integrate with commandline argument handling
|
||||
QCommandLineParser parser;
|
||||
aboutData.setupCommandLine(&parser);
|
||||
// setup of app specific commandline args
|
||||
|
||||
//Need to instantiate our slide
|
||||
QScopedPointer<Slide> slide(new Slide);
|
||||
QScopedPointer<File> filemanager(new File);
|
||||
|
||||
// apparently mpv needs this class set
|
||||
// let's register mpv as well
|
||||
std::setlocale(LC_NUMERIC, "C");
|
||||
qmlRegisterType<MpvObject>("mpv", 1, 0, "MpvObject");
|
||||
|
||||
//register our models
|
||||
qmlRegisterType<SongSqlModel>("org.presenter", 1, 0, "SongSqlModel");
|
||||
qmlRegisterType<VideoSqlModel>("org.presenter", 1, 0, "VideoSqlModel");
|
||||
qmlRegisterType<ImageSqlModel>("org.presenter", 1, 0, "ImageSqlModel");
|
||||
qmlRegisterType<PresentationSqlModel>("org.presenter", 1, 0, "PresentationSqlModel");
|
||||
qmlRegisterType<ServiceItemModel>("org.presenter", 1, 0, "ServiceItemModel");
|
||||
qmlRegisterType<MyObject>("org.presenter", 1, 0, "MyObject");
|
||||
qmlRegisterSingletonInstance("org.presenter", 1, 0, "SlideObject", slide.get());
|
||||
qmlRegisterSingletonInstance("org.presenter", 1, 0, "FileManager", filemanager.get());
|
||||
|
||||
connectToDatabase();
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
|
||||
engine.load(QUrl(QStringLiteral("qrc:qml/main.qml")));
|
||||
|
||||
// QQuickView *view = new QQuickView;
|
||||
// view->setSource(QUrl(QStringLiteral("qrc:qml/main.qml")));
|
||||
// view->show();
|
||||
|
||||
#ifdef STATIC_KIRIGAMI
|
||||
KirigamiPlugin::getInstance().registerTypes();
|
||||
#endif
|
||||
|
||||
if (engine.rootObjects().isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
154
src/cpp/mpv/mpvhelpers.h
Normal file
154
src/cpp/mpv/mpvhelpers.h
Normal file
|
@ -0,0 +1,154 @@
|
|||
#pragma once
|
||||
|
||||
// MpvObject definition
|
||||
#define READONLY_PROP_BOOL(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(bool varName READ varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
bool varName() const { return getProperty(p).toBool(); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(bool value);
|
||||
#define WRITABLE_PROP_BOOL(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(bool varName READ varName WRITE set_##varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
bool varName() const { return getProperty(p).toBool(); } \
|
||||
void set_##varName(bool value) { setProperty(p, value); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(bool value);
|
||||
|
||||
#define READONLY_PROP_INT(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(int varName READ varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
int varName() { return getProperty(p).toInt(); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(int value);
|
||||
#define WRITABLE_PROP_INT(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(int varName READ varName WRITE set_##varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
int varName() { return getProperty(p).toInt(); } \
|
||||
void set_##varName(int value) { setProperty(p, value); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(int value);
|
||||
|
||||
#define READONLY_PROP_DOUBLE(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(double varName READ varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
double varName() { return getProperty(p).toDouble(); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(double value);
|
||||
#define WRITABLE_PROP_DOUBLE(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(double varName READ varName WRITE set_##varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
double varName() { return getProperty(p).toDouble(); } \
|
||||
void set_##varName(double value) { setProperty(p, value); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(double value);
|
||||
|
||||
#define READONLY_PROP_STRING(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(QString varName READ varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
QString varName() { return getProperty(p).toString(); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(QString value);
|
||||
#define WRITABLE_PROP_STRING(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(QString varName READ varName WRITE set_##varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
QString varName() { return getProperty(p).toString(); } \
|
||||
void set_##varName(QString value) { setProperty(p, value); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(QString value);
|
||||
|
||||
#define READONLY_PROP_ARRAY(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(QVariantList varName READ varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
QVariantList varName() { return getProperty(p).toList(); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(QVariantList value);
|
||||
#define WRITABLE_PROP_ARRAY(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(QVariantList varName READ varName WRITE set_##varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
QVariantList varName() { return getProperty(p).toList(); } \
|
||||
void set_##varName(QVariantList value) { setProperty(p, value); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(QVariantList value);
|
||||
|
||||
#define READONLY_PROP_MAP(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(QVariantMap varName READ varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
QVariantMap varName() { return getProperty(p).toMap(); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(QVariantMap value);
|
||||
#define WRITABLE_PROP_MAP(p, varName) \
|
||||
public: \
|
||||
Q_PROPERTY(QVariantMap varName READ varName WRITE set_##varName NOTIFY varName##Changed) \
|
||||
public Q_SLOTS: \
|
||||
QVariantMap varName() { return getProperty(p).toMap(); } \
|
||||
void set_##varName(QVariantMap value) { setProperty(p, value); } \
|
||||
Q_SIGNALS: \
|
||||
void varName##Changed(QVariantMap value);
|
||||
|
||||
|
||||
|
||||
|
||||
// MpvObject() constructor
|
||||
#define WATCH_PROP_BOOL(p) \
|
||||
mpv_observe_property(mpv, 0, p, MPV_FORMAT_FLAG);
|
||||
#define WATCH_PROP_DOUBLE(p) \
|
||||
mpv_observe_property(mpv, 0, p, MPV_FORMAT_DOUBLE);
|
||||
#define WATCH_PROP_INT(p) \
|
||||
mpv_observe_property(mpv, 0, p, MPV_FORMAT_INT64);
|
||||
#define WATCH_PROP_STRING(p) \
|
||||
mpv_observe_property(mpv, 0, p, MPV_FORMAT_STRING);
|
||||
#define WATCH_PROP_ARRAY(p) \
|
||||
mpv_observe_property(mpv, 0, p, MPV_FORMAT_NODE_ARRAY);
|
||||
#define WATCH_PROP_MAP(p) \
|
||||
mpv_observe_property(mpv, 0, p, MPV_FORMAT_NODE_MAP);
|
||||
|
||||
|
||||
// MpvObject::handle_mpv_event()
|
||||
#define HANDLE_PROP_NONE(p, varName) \
|
||||
(strcmp(prop->name, p) == 0) { \
|
||||
int64_t value = 0; \
|
||||
Q_EMIT varName##Changed(value); \
|
||||
}
|
||||
#define HANDLE_PROP_BOOL(p, varName) \
|
||||
(strcmp(prop->name, p) == 0) { \
|
||||
bool value = *(bool *)prop->data; \
|
||||
Q_EMIT varName##Changed(value); \
|
||||
}
|
||||
#define HANDLE_PROP_INT(p, varName) \
|
||||
(strcmp(prop->name, p) == 0) { \
|
||||
int64_t value = *(int64_t *)prop->data; \
|
||||
Q_EMIT varName##Changed(value); \
|
||||
}
|
||||
#define HANDLE_PROP_DOUBLE(p, varName) \
|
||||
(strcmp(prop->name, p) == 0) { \
|
||||
double value = *(double *)prop->data; \
|
||||
Q_EMIT varName##Changed(value); \
|
||||
}
|
||||
#define HANDLE_PROP_STRING(p, varName) \
|
||||
(strcmp(prop->name, p) == 0) { \
|
||||
char* charValue = *(char**)prop->data; \
|
||||
QString value = QString::fromUtf8(charValue); \
|
||||
Q_EMIT varName##Changed(value); \
|
||||
}
|
||||
#define HANDLE_PROP_ARRAY(p, varName) \
|
||||
(strcmp(prop->name, p) == 0) { \
|
||||
QVariantList value = getProperty(p).toList(); \
|
||||
Q_EMIT varName##Changed(value); \
|
||||
}
|
||||
#define HANDLE_PROP_MAP(p, varName) \
|
||||
(strcmp(prop->name, p) == 0) { \
|
||||
QVariantMap value = getProperty(p).toMap(); \
|
||||
Q_EMIT varName##Changed(value); \
|
||||
}
|
570
src/cpp/mpv/mpvobject.cpp
Normal file
570
src/cpp/mpv/mpvobject.cpp
Normal file
|
@ -0,0 +1,570 @@
|
|||
#include "mpvobject.h"
|
||||
|
||||
// std
|
||||
#include <mpv/render.h>
|
||||
#include <qdir.h>
|
||||
#include <qvariant.h>
|
||||
#include <stdexcept>
|
||||
#include <clocale>
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
#include <QtGlobal>
|
||||
#include <QOpenGLContext>
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QtQuick/QQuickWindow>
|
||||
#include <QtQuick/QQuickView>
|
||||
|
||||
#include <QtQuick/QQuickFramebufferObject>
|
||||
#include <QtGui/QOpenGLFramebufferObject>
|
||||
|
||||
#include <QtX11Extras/QX11Info>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStandardPaths>
|
||||
|
||||
// libmpv
|
||||
#include <mpv/client.h>
|
||||
#include <mpv/render_gl.h>
|
||||
|
||||
// own
|
||||
#include "qthelper.hpp"
|
||||
|
||||
|
||||
const QDir writeDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
|
||||
//--- MpvRenderer
|
||||
void* MpvRenderer::get_proc_address(void *ctx, const char *name) {
|
||||
(void)ctx;
|
||||
QOpenGLContext *glctx = QOpenGLContext::currentContext();
|
||||
if (!glctx)
|
||||
return nullptr;
|
||||
return reinterpret_cast<void *>(glctx->getProcAddress(QByteArray(name)));
|
||||
}
|
||||
|
||||
MpvRenderer::MpvRenderer(const MpvObject *obj)
|
||||
: obj(obj)
|
||||
, mpv_gl(nullptr)
|
||||
{
|
||||
|
||||
// https://github.com/mpv-player/mpv/blob/master/libmpv/render_gl.h#L106
|
||||
#if MPV_CLIENT_API_VERSION >= MPV_MAKE_VERSION(2, 0)
|
||||
mpv_opengl_init_params gl_init_params{
|
||||
get_proc_address,
|
||||
nullptr // get_proc_address_ctx
|
||||
};
|
||||
#else
|
||||
mpv_opengl_init_params gl_init_params{
|
||||
get_proc_address,
|
||||
nullptr, // get_proc_address_ctx
|
||||
nullptr // extra_exts (deprecated)
|
||||
};
|
||||
#endif
|
||||
|
||||
mpv_render_param display{
|
||||
MPV_RENDER_PARAM_INVALID,
|
||||
nullptr
|
||||
};
|
||||
if (QX11Info::isPlatformX11()) {
|
||||
display.type = MPV_RENDER_PARAM_X11_DISPLAY;
|
||||
display.data = QX11Info::display();
|
||||
}
|
||||
mpv_render_param params[]{
|
||||
{ MPV_RENDER_PARAM_API_TYPE, const_cast<char *>(MPV_RENDER_API_TYPE_OPENGL) },
|
||||
{ MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params },
|
||||
display,
|
||||
{ MPV_RENDER_PARAM_INVALID, nullptr }
|
||||
};
|
||||
|
||||
if (mpv_render_context_create(&mpv_gl, obj->mpv, params) < 0)
|
||||
throw std::runtime_error("failed to initialize mpv GL context");
|
||||
|
||||
mpv_render_context_set_update_callback(mpv_gl, MpvObject::on_update, (void *)obj);
|
||||
}
|
||||
|
||||
MpvRenderer::~MpvRenderer() {
|
||||
if (mpv_gl)
|
||||
mpv_render_context_free(mpv_gl);
|
||||
|
||||
// mpv_destroy(obj->mpv);
|
||||
}
|
||||
|
||||
void MpvRenderer::render() {
|
||||
QOpenGLFramebufferObject *fbo = framebufferObject();
|
||||
// fbo->bind();
|
||||
obj->window()->resetOpenGLState();
|
||||
|
||||
// https://github.com/mpv-player/mpv/blob/master/libmpv/render_gl.h#L133
|
||||
mpv_opengl_fbo mpfbo{
|
||||
.fbo = static_cast<int>(fbo->handle()),
|
||||
.w = fbo->width(),
|
||||
.h = fbo->height(),
|
||||
.internal_format = 0 // 0=unknown
|
||||
};
|
||||
mpv_render_param params[] = {
|
||||
{ MPV_RENDER_PARAM_OPENGL_FBO, &mpfbo },
|
||||
{ MPV_RENDER_PARAM_INVALID, nullptr }
|
||||
};
|
||||
mpv_render_context_render(mpv_gl, params);
|
||||
|
||||
|
||||
obj->window()->resetOpenGLState();
|
||||
// fbo->release();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--- MpvObject
|
||||
static void wakeup(void *ctx)
|
||||
{
|
||||
QMetaObject::invokeMethod((MpvObject*)ctx, "onMpvEvents", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
MpvObject::MpvObject(QQuickItem *parent)
|
||||
: QQuickFramebufferObject(parent)
|
||||
, m_enableAudio(true)
|
||||
, m_useHwdec(false)
|
||||
, m_duration(0)
|
||||
, m_position(0)
|
||||
, m_isPlaying(false)
|
||||
{
|
||||
mpv = mpv_create();
|
||||
if (!mpv)
|
||||
throw std::runtime_error("could not create mpv context");
|
||||
|
||||
// these are the terminal messages
|
||||
// mpv_set_option_string(mpv, "terminal", "yes");
|
||||
// mpv_set_option_string(mpv, "msg-level", "all=warn,ao/alsa=error");
|
||||
// mpv_set_option_string(mpv, "msg-level", "all=debug");
|
||||
|
||||
//--- Hardware Decoding
|
||||
mpv::qt::set_option_variant(mpv, "hwdec-codecs", "all");
|
||||
|
||||
if (mpv_initialize(mpv) < 0)
|
||||
throw std::runtime_error("could not initialize mpv context");
|
||||
|
||||
|
||||
mpv::qt::set_option_variant(mpv, "audio-client-name", "mpvz");
|
||||
|
||||
mpv_request_log_messages(mpv, "terminal-default");
|
||||
|
||||
//--- 60fps Interpolation
|
||||
mpv::qt::set_option_variant(mpv, "interpolation", "yes");
|
||||
mpv::qt::set_option_variant(mpv, "video-sync", "display-resample");
|
||||
// mpv::qt::set_option_variant(mpv, "vf", "lavfi=\"fps=fps=60:round=down\"");
|
||||
// mpv::qt::set_option_variant(mpv, "override-display-fps", "60");
|
||||
|
||||
//--- ytdl 1080p max
|
||||
mpv::qt::set_option_variant(mpv, "ytdl-format", "ytdl-format=bestvideo[width<=?720]+bestaudio/best");
|
||||
|
||||
|
||||
mpv::qt::set_option_variant(mpv, "quiet", "yes");
|
||||
|
||||
// Setup the callback that will make QtQuick update and redraw if there
|
||||
// is a new video frame. Use a queued connection: this makes sure the
|
||||
// doUpdate() function is run on the GUI thread.
|
||||
// * MpvRender binds mpv_gl update function to MpvObject::on_update
|
||||
// * MpvObject::on_update will emit MpvObject::mpvUpdated
|
||||
connect(this, &MpvObject::mpvUpdated,
|
||||
this, &MpvObject::doUpdate,
|
||||
Qt::QueuedConnection);
|
||||
|
||||
WATCH_PROP_BOOL("idle-active")
|
||||
WATCH_PROP_BOOL("mute")
|
||||
WATCH_PROP_BOOL("pause")
|
||||
WATCH_PROP_BOOL("paused-for-cache")
|
||||
WATCH_PROP_BOOL("seekable")
|
||||
WATCH_PROP_INT("chapter")
|
||||
WATCH_PROP_INT("chapter-list/count")
|
||||
WATCH_PROP_INT("decoder-frame-drop-count")
|
||||
WATCH_PROP_INT("dheight")
|
||||
WATCH_PROP_INT("dwidth")
|
||||
WATCH_PROP_INT("estimated-frame-count")
|
||||
WATCH_PROP_INT("estimated-frame-number")
|
||||
WATCH_PROP_INT("frame-drop-count")
|
||||
WATCH_PROP_INT("playlist-pos")
|
||||
WATCH_PROP_INT("playlist/count")
|
||||
WATCH_PROP_INT("vo-delayed-frame-count")
|
||||
WATCH_PROP_INT("volume")
|
||||
WATCH_PROP_INT("vid")
|
||||
WATCH_PROP_INT("aid")
|
||||
WATCH_PROP_INT("sid")
|
||||
WATCH_PROP_INT("audio-params/channel-count")
|
||||
WATCH_PROP_INT("audio-params/samplerate")
|
||||
WATCH_PROP_INT("track-list/count")
|
||||
WATCH_PROP_INT("contrast")
|
||||
WATCH_PROP_INT("brightness")
|
||||
WATCH_PROP_INT("gamma")
|
||||
WATCH_PROP_INT("saturation")
|
||||
WATCH_PROP_INT("sub-margin-y")
|
||||
WATCH_PROP_DOUBLE("audio-bitrate")
|
||||
WATCH_PROP_DOUBLE("avsync")
|
||||
WATCH_PROP_DOUBLE("container-fps")
|
||||
WATCH_PROP_DOUBLE("demuxer-cache-duration")
|
||||
WATCH_PROP_DOUBLE("display-fps")
|
||||
WATCH_PROP_DOUBLE("duration")
|
||||
WATCH_PROP_DOUBLE("estimated-display-fps")
|
||||
WATCH_PROP_DOUBLE("estimated-vf-fps")
|
||||
WATCH_PROP_DOUBLE("fps")
|
||||
WATCH_PROP_DOUBLE("speed")
|
||||
WATCH_PROP_DOUBLE("time-pos")
|
||||
WATCH_PROP_DOUBLE("video-bitrate")
|
||||
WATCH_PROP_DOUBLE("video-params/aspect")
|
||||
WATCH_PROP_DOUBLE("video-out-params/aspect")
|
||||
WATCH_PROP_DOUBLE("window-scale")
|
||||
WATCH_PROP_DOUBLE("current-window-scale")
|
||||
WATCH_PROP_STRING("audio-codec")
|
||||
WATCH_PROP_STRING("audio-codec-name")
|
||||
WATCH_PROP_STRING("audio-params/format")
|
||||
WATCH_PROP_STRING("filename")
|
||||
WATCH_PROP_STRING("file-format")
|
||||
WATCH_PROP_STRING("file-size")
|
||||
WATCH_PROP_STRING("audio-format")
|
||||
WATCH_PROP_STRING("hwdec")
|
||||
WATCH_PROP_STRING("hwdec-current")
|
||||
WATCH_PROP_STRING("hwdec-interop")
|
||||
WATCH_PROP_STRING("loop")
|
||||
WATCH_PROP_STRING("media-title")
|
||||
WATCH_PROP_STRING("path")
|
||||
WATCH_PROP_STRING("video-codec")
|
||||
WATCH_PROP_STRING("video-format")
|
||||
WATCH_PROP_STRING("video-params/pixelformat")
|
||||
WATCH_PROP_STRING("video-out-params/pixelformat")
|
||||
WATCH_PROP_STRING("ytdl-format")
|
||||
WATCH_PROP_MAP("demuxer-cache-state")
|
||||
|
||||
connect(this, &MpvObject::idleActiveChanged,
|
||||
this, &MpvObject::updateState);
|
||||
connect(this, &MpvObject::pausedChanged,
|
||||
this, &MpvObject::updateState);
|
||||
|
||||
mpv_set_wakeup_callback(mpv, wakeup, this);
|
||||
}
|
||||
|
||||
MpvObject::~MpvObject()
|
||||
{
|
||||
// quit();
|
||||
}
|
||||
|
||||
QQuickFramebufferObject::Renderer *MpvObject::createRenderer() const
|
||||
{
|
||||
window()->setPersistentOpenGLContext(true);
|
||||
window()->setPersistentSceneGraph(true);
|
||||
return new MpvRenderer(this);
|
||||
}
|
||||
|
||||
void MpvObject::on_update(void *ctx)
|
||||
{
|
||||
MpvObject *self = (MpvObject *)ctx;
|
||||
emit self->mpvUpdated();
|
||||
}
|
||||
|
||||
// connected to mpvUpdated(); signal makes sure it runs on the GUI thread
|
||||
void MpvObject::doUpdate()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void MpvObject::command(const QVariant& params)
|
||||
{
|
||||
qDebug() << params;
|
||||
mpv::qt::command(mpv, params);
|
||||
}
|
||||
|
||||
void MpvObject::commandAsync(const QVariant& params)
|
||||
{
|
||||
// qDebug() << params;
|
||||
mpv::qt::command_async(mpv, params);
|
||||
}
|
||||
|
||||
void MpvObject::setProperty(const QString& name, const QVariant& value)
|
||||
{
|
||||
mpv::qt::set_property_variant(mpv, name, value);
|
||||
}
|
||||
|
||||
QVariant MpvObject::getProperty(const QString &name) const
|
||||
{
|
||||
return mpv::qt::get_property_variant(mpv, name);
|
||||
}
|
||||
|
||||
void MpvObject::setOption(const QString& name, const QVariant& value)
|
||||
{
|
||||
mpv::qt::set_option_variant(mpv, name, value);
|
||||
}
|
||||
|
||||
|
||||
void MpvObject::onMpvEvents()
|
||||
{
|
||||
// Process all events, until the event queue is empty.
|
||||
while (mpv) {
|
||||
mpv_event *event = mpv_wait_event(mpv, 0);
|
||||
if (event->event_id == MPV_EVENT_NONE) {
|
||||
break;
|
||||
}
|
||||
handle_mpv_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
void MpvObject::logPropChange(mpv_event_property *prop)
|
||||
{
|
||||
switch (prop->format) {
|
||||
case MPV_FORMAT_NONE:
|
||||
qDebug() << objectName() << "none" << prop->name << 0;
|
||||
break;
|
||||
case MPV_FORMAT_STRING:
|
||||
qDebug() << objectName() << "str " << prop->name << *(char**)prop->data;
|
||||
break;
|
||||
case MPV_FORMAT_FLAG:
|
||||
qDebug() << objectName() << "bool" << prop->name << *(bool *)prop->data;
|
||||
break;
|
||||
case MPV_FORMAT_INT64:
|
||||
qDebug() << objectName() << "int " << prop->name << *(int64_t *)prop->data;
|
||||
break;
|
||||
case MPV_FORMAT_DOUBLE:
|
||||
qDebug() << objectName() << "doub" << prop->name << *(double *)prop->data;
|
||||
break;
|
||||
case MPV_FORMAT_NODE_ARRAY:
|
||||
qDebug() << objectName() << "arr " << prop->name; // TODO
|
||||
break;
|
||||
case MPV_FORMAT_NODE_MAP:
|
||||
qDebug() << objectName() << "map " << prop->name; // TODO
|
||||
break;
|
||||
default:
|
||||
qDebug() << objectName() << "prop(format=" << prop->format << ")" << prop->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MpvObject::handle_mpv_event(mpv_event *event)
|
||||
{
|
||||
// See: https://github.com/mpv-player/mpv/blob/master/libmpv/client.h
|
||||
// See: https://github.com/mpv-player/mpv/blob/master/player/lua.c#L471
|
||||
|
||||
switch (event->event_id) {
|
||||
case MPV_EVENT_SHUTDOWN: {
|
||||
mpv_destroy(mpv);
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_LOG_MESSAGE: {
|
||||
mpv_event_log_message *logData = (mpv_event_log_message *)event->data;
|
||||
Q_EMIT logMessage(
|
||||
QString(logData->prefix),
|
||||
QString(logData->level),
|
||||
QString(logData->text)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_START_FILE: {
|
||||
Q_EMIT fileStarted();
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_END_FILE: {
|
||||
mpv_event_end_file *eef = (mpv_event_end_file *)event->data;
|
||||
const char *reason;
|
||||
switch (eef->reason) {
|
||||
case MPV_END_FILE_REASON_EOF: reason = "eof"; break;
|
||||
case MPV_END_FILE_REASON_STOP: reason = "stop"; break;
|
||||
case MPV_END_FILE_REASON_QUIT: reason = "quit"; break;
|
||||
case MPV_END_FILE_REASON_ERROR: reason = "error"; break;
|
||||
case MPV_END_FILE_REASON_REDIRECT: reason = "redirect"; break;
|
||||
default:
|
||||
reason = "unknown";
|
||||
}
|
||||
Q_EMIT fileEnded(QString(reason));
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_FILE_LOADED: {
|
||||
Q_EMIT fileLoaded();
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_PROPERTY_CHANGE: {
|
||||
mpv_event_property *prop = (mpv_event_property *)event->data;
|
||||
// logPropChange(prop);
|
||||
|
||||
if (prop->format == MPV_FORMAT_NONE) {
|
||||
if HANDLE_PROP_NONE("vid", vid)
|
||||
else if HANDLE_PROP_NONE("aid", aid)
|
||||
else if HANDLE_PROP_NONE("sid", sid)
|
||||
else if HANDLE_PROP_NONE("track-list/count", trackListCount)
|
||||
|
||||
} else if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
if (strcmp(prop->name, "time-pos") == 0) {
|
||||
double time = *(double *)prop->data;
|
||||
m_position = time;
|
||||
Q_EMIT positionChanged(time);
|
||||
} else if (strcmp(prop->name, "duration") == 0) {
|
||||
double time = *(double *)prop->data;
|
||||
m_duration = time;
|
||||
Q_EMIT durationChanged(time);
|
||||
}
|
||||
else if HANDLE_PROP_DOUBLE("audio-bitrate", audioBitrate)
|
||||
else if HANDLE_PROP_DOUBLE("avsync", avsync)
|
||||
else if HANDLE_PROP_DOUBLE("container-fps", containerFps)
|
||||
else if HANDLE_PROP_DOUBLE("demuxer-cache-duration", demuxerCacheDuration)
|
||||
else if HANDLE_PROP_DOUBLE("display-fps", displayFps)
|
||||
else if HANDLE_PROP_DOUBLE("estimated-display-fps", estimatedDisplayFps)
|
||||
else if HANDLE_PROP_DOUBLE("estimated-vf-fps", estimatedVfFps)
|
||||
else if HANDLE_PROP_DOUBLE("fps", fps)
|
||||
else if HANDLE_PROP_DOUBLE("speed", speed)
|
||||
else if HANDLE_PROP_DOUBLE("video-bitrate", videoBitrate)
|
||||
else if HANDLE_PROP_DOUBLE("video-params/aspect", videoParamsAspect)
|
||||
else if HANDLE_PROP_DOUBLE("video-out-params/aspect", videoOutParamsAspect)
|
||||
else if HANDLE_PROP_DOUBLE("window-scale", windowScale)
|
||||
else if HANDLE_PROP_DOUBLE("current-window-scale", currentWindowScale)
|
||||
|
||||
} else if (prop->format == MPV_FORMAT_FLAG) {
|
||||
if HANDLE_PROP_BOOL("idle-active", idleActive)
|
||||
else if HANDLE_PROP_BOOL("mute", muted)
|
||||
else if HANDLE_PROP_BOOL("pause", paused)
|
||||
else if HANDLE_PROP_BOOL("paused-for-cache", pausedForCache)
|
||||
else if HANDLE_PROP_BOOL("seekable", seekable)
|
||||
|
||||
} else if (prop->format == MPV_FORMAT_STRING) {
|
||||
if HANDLE_PROP_STRING("audio-codec", audioCodec)
|
||||
else if HANDLE_PROP_STRING("audio-codec-name", audioCodecName)
|
||||
else if HANDLE_PROP_STRING("audio-params/format", audioParamsFormat)
|
||||
else if HANDLE_PROP_STRING("filename", filename)
|
||||
else if HANDLE_PROP_STRING("file-format", fileFormat)
|
||||
else if HANDLE_PROP_STRING("file-size", fileSize)
|
||||
else if HANDLE_PROP_STRING("audio-format", audioFormat)
|
||||
else if HANDLE_PROP_STRING("hwdec", hwdec)
|
||||
else if HANDLE_PROP_STRING("hwdec-current", hwdecCurrent)
|
||||
else if HANDLE_PROP_STRING("hwdec-interop", hwdecInterop)
|
||||
else if HANDLE_PROP_STRING("loop", loop)
|
||||
else if HANDLE_PROP_STRING("media-title", mediaTitle)
|
||||
else if HANDLE_PROP_STRING("path", path)
|
||||
else if HANDLE_PROP_STRING("video-codec", videoCodec)
|
||||
else if HANDLE_PROP_STRING("video-format", videoFormat)
|
||||
else if HANDLE_PROP_STRING("video-params/pixelformat", videoParamsPixelformat)
|
||||
else if HANDLE_PROP_STRING("video-out-params/pixelformat", videoOutParamsPixelformat)
|
||||
else if HANDLE_PROP_STRING("ytdl-format", ytdlFormat)
|
||||
|
||||
|
||||
} else if (prop->format == MPV_FORMAT_INT64) {
|
||||
if HANDLE_PROP_INT("chapter", chapter)
|
||||
else if HANDLE_PROP_INT("chapter-list/count", chapterListCount)
|
||||
else if HANDLE_PROP_INT("decoder-frame-drop-count", decoderFrameDropCount)
|
||||
else if HANDLE_PROP_INT("dwidth", dwidth)
|
||||
else if HANDLE_PROP_INT("dheight", dheight)
|
||||
else if HANDLE_PROP_INT("estimated-frame-count", estimatedFrameCount)
|
||||
else if HANDLE_PROP_INT("estimated-frame-number", estimatedFrameNumber)
|
||||
else if HANDLE_PROP_INT("frame-drop-count", frameDropCount)
|
||||
else if HANDLE_PROP_INT("playlist-pos", playlistPos)
|
||||
else if HANDLE_PROP_INT("playlist/count", playlistCount)
|
||||
else if HANDLE_PROP_INT("vo-delayed-frame-count", voDelayedFrameCount)
|
||||
else if HANDLE_PROP_INT("volume", volume)
|
||||
else if HANDLE_PROP_INT("vid", vid)
|
||||
else if HANDLE_PROP_INT("aid", aid)
|
||||
else if HANDLE_PROP_INT("sid", sid)
|
||||
else if HANDLE_PROP_INT("audio-params/channel-count", audioParamsChannelCount)
|
||||
else if HANDLE_PROP_INT("audio-params/samplerate", audioParamsSampleRate)
|
||||
else if HANDLE_PROP_INT("track-list/count", trackListCount)
|
||||
else if HANDLE_PROP_INT("contrast", contrast)
|
||||
else if HANDLE_PROP_INT("brightness", brightness)
|
||||
else if HANDLE_PROP_INT("gamma", gamma)
|
||||
else if HANDLE_PROP_INT("saturation", saturation)
|
||||
else if HANDLE_PROP_INT("sub-margin-y", subMarginY)
|
||||
|
||||
|
||||
} else if (prop->format == MPV_FORMAT_NODE_MAP) {
|
||||
if HANDLE_PROP_MAP("demuxer-cache-state", demuxerCacheState)
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: ;
|
||||
// Ignore uninteresting or unknown events.
|
||||
}
|
||||
}
|
||||
|
||||
void MpvObject::play()
|
||||
{
|
||||
// qDebug() << "play";
|
||||
if (idleActive() && playlistCount() >= 1) { // File has finished playing.
|
||||
// qDebug() << "\treload";
|
||||
set_playlistPos(playlistPos()); // Reload and play file again.
|
||||
}
|
||||
if (!isPlaying()) {
|
||||
// qDebug() << "\t!isPlaying";
|
||||
set_paused(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MpvObject::pause()
|
||||
{
|
||||
// qDebug() << "pause";
|
||||
if (isPlaying()) {
|
||||
qDebug() << "!isPlaying";
|
||||
set_paused(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MpvObject::playPause()
|
||||
{
|
||||
if (isPlaying()) {
|
||||
pause();
|
||||
} else {
|
||||
play();
|
||||
}
|
||||
}
|
||||
|
||||
void MpvObject::stop()
|
||||
{
|
||||
command(QVariantList() << "stop");
|
||||
}
|
||||
|
||||
void MpvObject::quit()
|
||||
{
|
||||
command(QVariantList() << "quit");
|
||||
qDebug() << "We quit mpv";
|
||||
}
|
||||
|
||||
void MpvObject::stepBackward()
|
||||
{
|
||||
command(QVariantList() << "frame-back-step");
|
||||
}
|
||||
|
||||
void MpvObject::stepForward()
|
||||
{
|
||||
command(QVariantList() << "frame-step");
|
||||
}
|
||||
|
||||
void MpvObject::seek(double pos)
|
||||
{
|
||||
// qDebug() << "seek" << pos;
|
||||
pos = qMax(0.0, qMin(pos, m_duration));
|
||||
commandAsync(QVariantList() << "seek" << pos << "absolute");
|
||||
}
|
||||
|
||||
void MpvObject::loadFile(QVariant urls)
|
||||
{
|
||||
qDebug() << "Url being loaded: " << urls;
|
||||
command(QVariantList() << "loadfile" << urls);
|
||||
}
|
||||
|
||||
void MpvObject::screenshotToFile(QUrl url) {
|
||||
qDebug() << "Url of screenshot to be taken: " << url;
|
||||
QDir dir = writeDir.absolutePath() + "/presenter/Church Presenter/thumbnails";
|
||||
qDebug() << "thumbnails dir: " << dir;
|
||||
QDir absDir = writeDir.absolutePath() + "/presenter/Church Presenter";
|
||||
if (!dir.exists())
|
||||
absDir.mkdir("thumbnails");
|
||||
QString file = url.path() + ".jpg";
|
||||
commandAsync(QVariantList() << "screenshot-to-file" << file << "video");
|
||||
}
|
||||
|
||||
void MpvObject::subAdd(QVariant urls)
|
||||
{
|
||||
command(QVariantList() << "sub-add" << urls);
|
||||
}
|
||||
|
||||
|
||||
void MpvObject::updateState()
|
||||
{
|
||||
bool isNowPlaying = !idleActive() && !paused();
|
||||
if (m_isPlaying != isNowPlaying) {
|
||||
m_isPlaying = isNowPlaying;
|
||||
emit isPlayingChanged(m_isPlaying);
|
||||
}
|
||||
}
|
||||
|
205
src/cpp/mpv/mpvobject.h
Normal file
205
src/cpp/mpv/mpvobject.h
Normal file
|
@ -0,0 +1,205 @@
|
|||
#pragma once
|
||||
|
||||
#include "mpvhelpers.h"
|
||||
|
||||
// Qt
|
||||
#include <QtQuick/QQuickItem>
|
||||
#include <QtQuick/QQuickFramebufferObject>
|
||||
|
||||
// libmpv
|
||||
#include <mpv/client.h>
|
||||
#include <mpv/render_gl.h>
|
||||
|
||||
// own
|
||||
#include "qthelper.hpp"
|
||||
|
||||
|
||||
class MpvObject;
|
||||
class MpvRenderer;
|
||||
|
||||
class MpvRenderer : public QQuickFramebufferObject::Renderer
|
||||
{
|
||||
static void* get_proc_address(void *ctx, const char *name);
|
||||
|
||||
public:
|
||||
MpvRenderer(const MpvObject *obj);
|
||||
virtual ~MpvRenderer();
|
||||
|
||||
void render();
|
||||
|
||||
private:
|
||||
const MpvObject *obj;
|
||||
mpv_render_context *mpv_gl;
|
||||
};
|
||||
|
||||
|
||||
class MpvObject : public QQuickFramebufferObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class MpvRenderer;
|
||||
|
||||
Q_PROPERTY(bool enableAudio READ enableAudio WRITE setEnableAudio NOTIFY enableAudioChanged)
|
||||
Q_PROPERTY(bool useHwdec READ useHwdec WRITE setUseHwdec NOTIFY useHwdecChanged)
|
||||
|
||||
READONLY_PROP_BOOL("idle-active", idleActive)
|
||||
WRITABLE_PROP_BOOL("mute", muted)
|
||||
WRITABLE_PROP_BOOL("pause", paused)
|
||||
READONLY_PROP_BOOL("paused-for-cache", pausedForCache)
|
||||
READONLY_PROP_BOOL("seekable", seekable)
|
||||
READONLY_PROP_INT("chapter", chapter)
|
||||
READONLY_PROP_INT("chapter-list/count", chapterListCount) // OR "chapters"
|
||||
READONLY_PROP_INT("decoder-frame-drop-count", decoderFrameDropCount)
|
||||
READONLY_PROP_INT("dheight", dheight)
|
||||
READONLY_PROP_INT("dwidth", dwidth)
|
||||
READONLY_PROP_INT("estimated-frame-count", estimatedFrameCount)
|
||||
READONLY_PROP_INT("estimated-frame-number", estimatedFrameNumber)
|
||||
READONLY_PROP_INT("frame-drop-count", frameDropCount)
|
||||
WRITABLE_PROP_INT("playlist-pos", playlistPos)
|
||||
READONLY_PROP_INT("playlist/count", playlistCount)
|
||||
WRITABLE_PROP_INT("vo-delayed-frame-count", voDelayedFrameCount)
|
||||
WRITABLE_PROP_INT("volume", volume)
|
||||
WRITABLE_PROP_INT("contrast", contrast)
|
||||
WRITABLE_PROP_INT("brightness", brightness)
|
||||
WRITABLE_PROP_INT("gamma", gamma)
|
||||
WRITABLE_PROP_INT("saturation", saturation)
|
||||
WRITABLE_PROP_INT("sub-margin-y", subMarginY)
|
||||
READONLY_PROP_INT("vid", vid)
|
||||
READONLY_PROP_INT("aid", aid)
|
||||
READONLY_PROP_INT("sid", sid)
|
||||
READONLY_PROP_INT("audio-params/channel-count", audioParamsChannelCount)
|
||||
READONLY_PROP_INT("audio-params/samplerate", audioParamsSampleRate)
|
||||
READONLY_PROP_INT("track-list/count", trackListCount)
|
||||
READONLY_PROP_DOUBLE("audio-bitrate", audioBitrate)
|
||||
READONLY_PROP_DOUBLE("avsync", avsync)
|
||||
READONLY_PROP_DOUBLE("container-fps", containerFps)
|
||||
READONLY_PROP_DOUBLE("demuxer-cache-duration", demuxerCacheDuration)
|
||||
READONLY_PROP_DOUBLE("display-fps", displayFps)
|
||||
READONLY_PROP_DOUBLE("estimated-display-fps", estimatedDisplayFps)
|
||||
READONLY_PROP_DOUBLE("estimated-vf-fps", estimatedVfFps)
|
||||
READONLY_PROP_DOUBLE("fps", fps) // Deprecated, use "container-fps"
|
||||
WRITABLE_PROP_DOUBLE("speed", speed)
|
||||
READONLY_PROP_DOUBLE("video-bitrate", videoBitrate)
|
||||
READONLY_PROP_DOUBLE("video-params/aspect", videoParamsAspect)
|
||||
READONLY_PROP_DOUBLE("video-out-params/aspect", videoOutParamsAspect)
|
||||
WRITABLE_PROP_DOUBLE("window-scale", windowScale)
|
||||
READONLY_PROP_DOUBLE("current-window-scale", currentWindowScale)
|
||||
READONLY_PROP_STRING("audio-params/format", audioParamsFormat)
|
||||
READONLY_PROP_STRING("audio-codec", audioCodec)
|
||||
READONLY_PROP_STRING("audio-codec-name", audioCodecName)
|
||||
READONLY_PROP_STRING("filename", filename)
|
||||
READONLY_PROP_STRING("file-format", fileFormat)
|
||||
READONLY_PROP_STRING("file-size", fileSize)
|
||||
READONLY_PROP_STRING("audio-format", audioFormat)
|
||||
WRITABLE_PROP_STRING("hwdec", hwdec)
|
||||
READONLY_PROP_STRING("hwdec-current", hwdecCurrent)
|
||||
READONLY_PROP_STRING("hwdec-interop", hwdecInterop)
|
||||
WRITABLE_PROP_STRING("loop", loop)
|
||||
READONLY_PROP_STRING("media-title", mediaTitle)
|
||||
READONLY_PROP_STRING("path", path)
|
||||
READONLY_PROP_STRING("video-codec", videoCodec)
|
||||
READONLY_PROP_STRING("video-format", videoFormat)
|
||||
READONLY_PROP_STRING("video-params/pixelformat", videoParamsPixelformat)
|
||||
READONLY_PROP_STRING("video-out-params/pixelformat", videoOutParamsPixelformat)
|
||||
READONLY_PROP_STRING("ytdl-format", ytdlFormat)
|
||||
READONLY_PROP_MAP("demuxer-cache-state", demuxerCacheState)
|
||||
|
||||
public:
|
||||
Q_PROPERTY(bool isPlaying READ isPlaying NOTIFY isPlayingChanged)
|
||||
Q_PROPERTY(double duration READ duration NOTIFY durationChanged)
|
||||
Q_PROPERTY(double position READ position NOTIFY positionChanged)
|
||||
|
||||
public:
|
||||
MpvObject(QQuickItem *parent = nullptr);
|
||||
virtual ~MpvObject();
|
||||
|
||||
virtual Renderer *createRenderer() const;
|
||||
|
||||
Q_INVOKABLE void setProperty(const QString& name, const QVariant& value);
|
||||
Q_INVOKABLE QVariant getProperty(const QString& name) const;
|
||||
Q_INVOKABLE void setOption(const QString& name, const QVariant& value);
|
||||
|
||||
Q_INVOKABLE QString getPlaylistFilename(int playlistIndex) const { return getProperty(QString("playlist/%1/filename").arg(playlistIndex)).toString(); }
|
||||
Q_INVOKABLE QString getPlaylistTitle(int playlistIndex) const { return getProperty(QString("playlist/%1/title").arg(playlistIndex)).toString(); }
|
||||
Q_INVOKABLE QString getChapterTitle(int chapterIndex) const { return getProperty(QString("chapter-list/%1/title").arg(chapterIndex)).toString(); }
|
||||
Q_INVOKABLE double getChapterTime(int chapterIndex) const { return getProperty(QString("chapter-list/%1/time").arg(chapterIndex)).toDouble(); }
|
||||
|
||||
public slots:
|
||||
void command(const QVariant& params);
|
||||
void commandAsync(const QVariant& params);
|
||||
|
||||
void playPause();
|
||||
void play();
|
||||
void pause();
|
||||
void stop();
|
||||
void quit();
|
||||
void stepBackward();
|
||||
void stepForward();
|
||||
void seek(double pos);
|
||||
void loadFile(QVariant urls);
|
||||
void screenshotToFile(QUrl url);
|
||||
void subAdd(QVariant urls);
|
||||
|
||||
bool enableAudio() const { return m_enableAudio; }
|
||||
void setEnableAudio(bool value) {
|
||||
if (m_enableAudio != value) {
|
||||
m_enableAudio = value;
|
||||
Q_EMIT enableAudioChanged(value);
|
||||
}
|
||||
if (!m_enableAudio) {
|
||||
mpv::qt::set_option_variant(mpv, "ao", "null");
|
||||
}
|
||||
}
|
||||
|
||||
bool useHwdec() const { return m_useHwdec; }
|
||||
void setUseHwdec(bool value) {
|
||||
if (m_useHwdec != value) {
|
||||
m_useHwdec = value;
|
||||
if (m_useHwdec) {
|
||||
mpv::qt::set_option_variant(mpv, "hwdec", "auto-copy");
|
||||
} else {
|
||||
mpv::qt::set_option_variant(mpv, "hwdec", "no");
|
||||
}
|
||||
Q_EMIT useHwdecChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool isPlaying() const { return m_isPlaying; }
|
||||
void updateState();
|
||||
|
||||
double duration() const { return m_duration; }
|
||||
double position() const { return m_position; }
|
||||
|
||||
signals:
|
||||
void enableAudioChanged(bool value);
|
||||
void useHwdecChanged(bool value);
|
||||
void isPlayingChanged(bool value);
|
||||
|
||||
void durationChanged(double value); // Unit: seconds
|
||||
void positionChanged(double value); // Unit: seconds
|
||||
|
||||
void mpvUpdated();
|
||||
|
||||
void logMessage(QString prefix, QString level, QString text);
|
||||
void fileStarted();
|
||||
void fileEnded(QString reason);
|
||||
void fileLoaded();
|
||||
|
||||
private slots:
|
||||
void onMpvEvents();
|
||||
void doUpdate();
|
||||
|
||||
protected:
|
||||
mpv_handle *mpv;
|
||||
|
||||
private:
|
||||
void logPropChange(mpv_event_property *prop);
|
||||
void handle_mpv_event(mpv_event *event);
|
||||
static void on_update(void *ctx);
|
||||
|
||||
bool m_enableAudio;
|
||||
bool m_useHwdec;
|
||||
double m_duration;
|
||||
double m_position;
|
||||
bool m_isPlaying;
|
||||
};
|
370
src/cpp/mpv/qthelper.hpp
Normal file
370
src/cpp/mpv/qthelper.hpp
Normal file
|
@ -0,0 +1,370 @@
|
|||
#pragma once
|
||||
|
||||
// libmpv
|
||||
#include <mpv/client.h>
|
||||
|
||||
// std
|
||||
#include <cstring>
|
||||
|
||||
// Qt
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
#include <QSharedPointer>
|
||||
#include <QMetaType>
|
||||
|
||||
namespace mpv {
|
||||
namespace qt {
|
||||
|
||||
// Wrapper around mpv_handle. Does refcounting under the hood.
|
||||
class Handle
|
||||
{
|
||||
struct container {
|
||||
container(mpv_handle *h) : mpv(h) {}
|
||||
~container() { mpv_terminate_destroy(mpv); }
|
||||
mpv_handle *mpv;
|
||||
};
|
||||
QSharedPointer<container> sptr;
|
||||
public:
|
||||
// Construct a new Handle from a raw mpv_handle with refcount 1. If the
|
||||
// last Handle goes out of scope, the mpv_handle will be destroyed with
|
||||
// mpv_terminate_destroy().
|
||||
// Never destroy the mpv_handle manually when using this wrapper. You
|
||||
// will create dangling pointers. Just let the wrapper take care of
|
||||
// destroying the mpv_handle.
|
||||
// Never create multiple wrappers from the same raw mpv_handle; copy the
|
||||
// wrapper instead (that's what it's for).
|
||||
static Handle FromRawHandle(mpv_handle *handle) {
|
||||
Handle h;
|
||||
h.sptr = QSharedPointer<container>(new container(handle));
|
||||
return h;
|
||||
}
|
||||
|
||||
// Return the raw handle; for use with the libmpv C API.
|
||||
operator mpv_handle*() const { return sptr ? (*sptr).mpv : 0; }
|
||||
};
|
||||
|
||||
static inline QVariant node_to_variant(const mpv_node *node)
|
||||
{
|
||||
switch (node->format) {
|
||||
case MPV_FORMAT_STRING:
|
||||
return QVariant(QString::fromUtf8(node->u.string));
|
||||
case MPV_FORMAT_FLAG:
|
||||
return QVariant(static_cast<bool>(node->u.flag));
|
||||
case MPV_FORMAT_INT64:
|
||||
return QVariant(static_cast<qlonglong>(node->u.int64));
|
||||
case MPV_FORMAT_DOUBLE:
|
||||
return QVariant(node->u.double_);
|
||||
case MPV_FORMAT_NODE_ARRAY: {
|
||||
mpv_node_list *list = node->u.list;
|
||||
QVariantList qlist;
|
||||
for (int n = 0; n < list->num; n++)
|
||||
qlist.append(node_to_variant(&list->values[n]));
|
||||
return QVariant(qlist);
|
||||
}
|
||||
case MPV_FORMAT_NODE_MAP: {
|
||||
mpv_node_list *list = node->u.list;
|
||||
QVariantMap qmap;
|
||||
for (int n = 0; n < list->num; n++) {
|
||||
qmap.insert(QString::fromUtf8(list->keys[n]),
|
||||
node_to_variant(&list->values[n]));
|
||||
}
|
||||
return QVariant(qmap);
|
||||
}
|
||||
default: // MPV_FORMAT_NONE, unknown values (e.g. future extensions)
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
struct node_builder {
|
||||
node_builder(const QVariant& v) {
|
||||
set(&node_, v);
|
||||
}
|
||||
~node_builder() {
|
||||
free_node(&node_);
|
||||
}
|
||||
mpv_node *node() { return &node_; }
|
||||
private:
|
||||
Q_DISABLE_COPY(node_builder)
|
||||
mpv_node node_;
|
||||
mpv_node_list *create_list(mpv_node *dst, bool is_map, int num) {
|
||||
dst->format = is_map ? MPV_FORMAT_NODE_MAP : MPV_FORMAT_NODE_ARRAY;
|
||||
mpv_node_list *list = new mpv_node_list();
|
||||
dst->u.list = list;
|
||||
if (!list)
|
||||
goto err;
|
||||
list->values = new mpv_node[num]();
|
||||
if (!list->values)
|
||||
goto err;
|
||||
if (is_map) {
|
||||
list->keys = new char*[num]();
|
||||
if (!list->keys)
|
||||
goto err;
|
||||
}
|
||||
return list;
|
||||
err:
|
||||
free_node(dst);
|
||||
return NULL;
|
||||
}
|
||||
char *dup_qstring(const QString &s) {
|
||||
QByteArray b = s.toUtf8();
|
||||
char *r = new char[b.size() + 1];
|
||||
if (r)
|
||||
std::memcpy(r, b.data(), b.size() + 1);
|
||||
return r;
|
||||
}
|
||||
bool test_type(const QVariant &v, QMetaType::Type t) {
|
||||
// The Qt docs say: "Although this function is declared as returning
|
||||
// "QVariant::Type(obsolete), the return value should be interpreted
|
||||
// as QMetaType::Type."
|
||||
// So a cast really seems to be needed to avoid warnings (urgh).
|
||||
return static_cast<int>(v.type()) == static_cast<int>(t);
|
||||
}
|
||||
void set(mpv_node *dst, const QVariant &src) {
|
||||
if (test_type(src, QMetaType::QString)) {
|
||||
dst->format = MPV_FORMAT_STRING;
|
||||
dst->u.string = dup_qstring(src.toString());
|
||||
if (!dst->u.string)
|
||||
goto fail;
|
||||
} else if (test_type(src, QMetaType::Bool)) {
|
||||
dst->format = MPV_FORMAT_FLAG;
|
||||
dst->u.flag = src.toBool() ? 1 : 0;
|
||||
} else if (test_type(src, QMetaType::Int) ||
|
||||
test_type(src, QMetaType::LongLong) ||
|
||||
test_type(src, QMetaType::UInt) ||
|
||||
test_type(src, QMetaType::ULongLong))
|
||||
{
|
||||
dst->format = MPV_FORMAT_INT64;
|
||||
dst->u.int64 = src.toLongLong();
|
||||
} else if (test_type(src, QMetaType::Double)) {
|
||||
dst->format = MPV_FORMAT_DOUBLE;
|
||||
dst->u.double_ = src.toDouble();
|
||||
} else if (src.canConvert<QVariantList>()) {
|
||||
QVariantList qlist = src.toList();
|
||||
mpv_node_list *list = create_list(dst, false, qlist.size());
|
||||
if (!list)
|
||||
goto fail;
|
||||
list->num = qlist.size();
|
||||
for (int n = 0; n < qlist.size(); n++)
|
||||
set(&list->values[n], qlist[n]);
|
||||
} else if (src.canConvert<QVariantMap>()) {
|
||||
QVariantMap qmap = src.toMap();
|
||||
mpv_node_list *list = create_list(dst, true, qmap.size());
|
||||
if (!list)
|
||||
goto fail;
|
||||
list->num = qmap.size();
|
||||
for (int n = 0; n < qmap.size(); n++) {
|
||||
list->keys[n] = dup_qstring(qmap.keys()[n]);
|
||||
if (!list->keys[n]) {
|
||||
free_node(dst);
|
||||
goto fail;
|
||||
}
|
||||
set(&list->values[n], qmap.values()[n]);
|
||||
}
|
||||
} else {
|
||||
goto fail;
|
||||
}
|
||||
return;
|
||||
fail:
|
||||
dst->format = MPV_FORMAT_NONE;
|
||||
}
|
||||
void free_node(mpv_node *dst) {
|
||||
switch (dst->format) {
|
||||
case MPV_FORMAT_STRING:
|
||||
delete[] dst->u.string;
|
||||
break;
|
||||
case MPV_FORMAT_NODE_ARRAY:
|
||||
case MPV_FORMAT_NODE_MAP: {
|
||||
mpv_node_list *list = dst->u.list;
|
||||
if (list) {
|
||||
for (int n = 0; n < list->num; n++) {
|
||||
if (list->keys)
|
||||
delete[] list->keys[n];
|
||||
if (list->values)
|
||||
free_node(&list->values[n]);
|
||||
}
|
||||
delete[] list->keys;
|
||||
delete[] list->values;
|
||||
}
|
||||
delete list;
|
||||
break;
|
||||
}
|
||||
default: ;
|
||||
}
|
||||
dst->format = MPV_FORMAT_NONE;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* RAII wrapper that calls mpv_free_node_contents() on the pointer.
|
||||
*/
|
||||
struct node_autofree {
|
||||
mpv_node *ptr;
|
||||
node_autofree(mpv_node *a_ptr) : ptr(a_ptr) {}
|
||||
~node_autofree() { mpv_free_node_contents(ptr); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the given property as mpv_node converted to QVariant, or QVariant()
|
||||
* on error.
|
||||
*
|
||||
* @deprecated use get_property() instead
|
||||
*
|
||||
* @param name the property name
|
||||
*/
|
||||
static inline QVariant get_property_variant(mpv_handle *ctx, const QString &name)
|
||||
{
|
||||
mpv_node node;
|
||||
if (mpv_get_property(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, &node) < 0)
|
||||
return QVariant();
|
||||
node_autofree f(&node);
|
||||
return node_to_variant(&node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given property as mpv_node converted from the QVariant argument.
|
||||
* @deprecated use set_property() instead
|
||||
*/
|
||||
static inline int set_property_variant(mpv_handle *ctx, const QString &name,
|
||||
const QVariant &v)
|
||||
{
|
||||
node_builder node(v);
|
||||
return mpv_set_property(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, node.node());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given option as mpv_node converted from the QVariant argument.
|
||||
*
|
||||
* @deprecated use set_property() instead
|
||||
*/
|
||||
static inline int set_option_variant(mpv_handle *ctx, const QString &name,
|
||||
const QVariant &v)
|
||||
{
|
||||
node_builder node(v);
|
||||
return mpv_set_option(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, node.node());
|
||||
}
|
||||
|
||||
/**
|
||||
* mpv_command_node() equivalent. Returns QVariant() on error (and
|
||||
* unfortunately, the same on success).
|
||||
*
|
||||
* @deprecated use command() instead
|
||||
*/
|
||||
static inline QVariant command_variant(mpv_handle *ctx, const QVariant &args)
|
||||
{
|
||||
node_builder node(args);
|
||||
mpv_node res;
|
||||
if (mpv_command_node(ctx, node.node(), &res) < 0)
|
||||
return QVariant();
|
||||
node_autofree f(&res);
|
||||
return node_to_variant(&res);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to return error codes wrapped in QVariant for functions which
|
||||
* return QVariant.
|
||||
*
|
||||
* You can use get_error() or is_error() to extract the error status from a
|
||||
* QVariant value.
|
||||
*/
|
||||
struct ErrorReturn
|
||||
{
|
||||
/**
|
||||
* enum mpv_error value (or a value outside of it if ABI was extended)
|
||||
*/
|
||||
int error;
|
||||
|
||||
ErrorReturn() : error(0) {}
|
||||
explicit ErrorReturn(int err) : error(err) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the mpv error code packed into a QVariant, or 0 (success) if it's not
|
||||
* an error value.
|
||||
*
|
||||
* @return error code (<0) or success (>=0)
|
||||
*/
|
||||
static inline int get_error(const QVariant &v)
|
||||
{
|
||||
if (!v.canConvert<ErrorReturn>())
|
||||
return 0;
|
||||
return v.value<ErrorReturn>().error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the QVariant carries a mpv error code.
|
||||
*/
|
||||
static inline bool is_error(const QVariant &v)
|
||||
{
|
||||
return get_error(v) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the given property as mpv_node converted to QVariant, or QVariant()
|
||||
* on error.
|
||||
*
|
||||
* @param name the property name
|
||||
* @return the property value, or an ErrorReturn with the error code
|
||||
*/
|
||||
static inline QVariant get_property(mpv_handle *ctx, const QString &name)
|
||||
{
|
||||
mpv_node node;
|
||||
int err = mpv_get_property(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, &node);
|
||||
if (err < 0)
|
||||
return QVariant::fromValue(ErrorReturn(err));
|
||||
node_autofree f(&node);
|
||||
return node_to_variant(&node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given property as mpv_node converted from the QVariant argument.
|
||||
*
|
||||
* @return mpv error code (<0 on error, >= 0 on success)
|
||||
*/
|
||||
static inline int set_property(mpv_handle *ctx, const QString &name,
|
||||
const QVariant &v)
|
||||
{
|
||||
node_builder node(v);
|
||||
return mpv_set_property(ctx, name.toUtf8().data(), MPV_FORMAT_NODE, node.node());
|
||||
}
|
||||
|
||||
/**
|
||||
* mpv_command_node() equivalent.
|
||||
*
|
||||
* @param args command arguments, with args[0] being the command name as string
|
||||
* @return the property value, or an ErrorReturn with the error code
|
||||
*/
|
||||
static inline QVariant command(mpv_handle *ctx, const QVariant &args)
|
||||
{
|
||||
node_builder node(args);
|
||||
mpv_node res;
|
||||
int err = mpv_command_node(ctx, node.node(), &res);
|
||||
if (err < 0)
|
||||
return QVariant::fromValue(ErrorReturn(err));
|
||||
node_autofree f(&res);
|
||||
return node_to_variant(&res);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpv_command_node_async() equivalent.
|
||||
*
|
||||
* @param args command arguments, with args[0] being the command name as string
|
||||
* @return empty QVariant, or an ErrorReturn with the error code
|
||||
*/
|
||||
static inline QVariant command_async(mpv_handle *ctx, const QVariant &args)
|
||||
{
|
||||
node_builder node(args);
|
||||
quint64 replyUserdata = 0; // TODO: Bomi casted args[0] to int. Bomi's args was a QByteArray however.
|
||||
int err = mpv_command_node_async(ctx, replyUserdata, node.node());
|
||||
if (err < 0)
|
||||
return QVariant::fromValue(ErrorReturn(err));
|
||||
// TODO: Return unique replyUserdata so the app can wait for
|
||||
// the result in an MPV_EVENT_COMMAND_REPLY event.
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(mpv::qt::ErrorReturn)
|
203
src/cpp/presentationsqlmodel.cpp
Normal file
203
src/cpp/presentationsqlmodel.cpp
Normal file
|
@ -0,0 +1,203 @@
|
|||
#include "presentationsqlmodel.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QSqlError>
|
||||
#include <QSqlRecord>
|
||||
#include <QSqlQuery>
|
||||
#include <QSql>
|
||||
// #include <QPdfDocument>
|
||||
#include <QSqlDatabase>
|
||||
#include <QFileInfo>
|
||||
#include <qabstractitemmodel.h>
|
||||
#include <qdebug.h>
|
||||
#include <qnamespace.h>
|
||||
#include <qobject.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qsqlrecord.h>
|
||||
#include <qurl.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
static const char *presentationsTableName = "presentations";
|
||||
|
||||
static void createPresentationTable()
|
||||
{
|
||||
QSqlQuery query;
|
||||
if(QSqlDatabase::database().tables().contains(presentationsTableName)) {
|
||||
// query.exec("DROP TABLE 'presentations'");
|
||||
// qDebug() << query.lastQuery();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!query.exec("CREATE TABLE IF NOT EXISTS 'presentations' ("
|
||||
" 'id' INTEGER NOT NULL,"
|
||||
" 'title' TEXT NOT NULL,"
|
||||
" 'filePath' TEXT NOT NULL,"
|
||||
" PRIMARY KEY(id))")) {
|
||||
qFatal("Failed to query database: %s",
|
||||
qPrintable(query.lastError().text()));
|
||||
}
|
||||
qDebug() << query.lastQuery();
|
||||
qDebug() << "inserting into presentations";
|
||||
|
||||
query.exec("INSERT INTO presentations (title, filePath) VALUES ('Dec 180', 'file:///home/chris/nextcloud/tfc/openlp/5 slides-1.pdf')");
|
||||
qDebug() << query.lastQuery();
|
||||
query.exec("INSERT INTO presentations (title, filePath) VALUES ('No TFC', "
|
||||
"'file:///home/chris/nextcloud/tfc/openlp/5 slides-2.pdf')");
|
||||
|
||||
query.exec("select * from presentations");
|
||||
qDebug() << query.lastQuery();
|
||||
}
|
||||
|
||||
PresentationSqlModel::PresentationSqlModel(QObject *parent) : QSqlTableModel(parent) {
|
||||
qDebug() << "creating presentation table";
|
||||
createPresentationTable();
|
||||
setTable(presentationsTableName);
|
||||
setEditStrategy(QSqlTableModel::OnManualSubmit);
|
||||
// make sure to call select else the model won't fill
|
||||
select();
|
||||
}
|
||||
|
||||
QVariant PresentationSqlModel::data(const QModelIndex &index, int role) const {
|
||||
if (role < Qt::UserRole) {
|
||||
return QSqlTableModel::data(index, role);
|
||||
}
|
||||
|
||||
// qDebug() << role;
|
||||
const QSqlRecord sqlRecord = record(index.row());
|
||||
return sqlRecord.value(role - Qt::UserRole);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> PresentationSqlModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> names;
|
||||
names[Qt::UserRole] = "id";
|
||||
names[Qt::UserRole + 1] = "title";
|
||||
names[Qt::UserRole + 2] = "filePath";
|
||||
return names;
|
||||
}
|
||||
|
||||
void PresentationSqlModel::newPresentation(const QUrl &filePath) {
|
||||
qDebug() << "adding new presentation";
|
||||
int rows = rowCount();
|
||||
|
||||
qDebug() << rows;
|
||||
QSqlRecord recordData = record();
|
||||
QFileInfo fileInfo = filePath.toString();
|
||||
QString title = fileInfo.baseName();
|
||||
recordData.setValue("title", title);
|
||||
recordData.setValue("filePath", filePath);
|
||||
|
||||
if (insertRecord(rows, recordData)) {
|
||||
submitAll();
|
||||
} else {
|
||||
qDebug() << lastError();
|
||||
};
|
||||
}
|
||||
|
||||
void PresentationSqlModel::deletePresentation(const int &row) {
|
||||
QSqlRecord recordData = record(row);
|
||||
if (recordData.isEmpty())
|
||||
return;
|
||||
|
||||
removeRow(row);
|
||||
submitAll();
|
||||
}
|
||||
|
||||
int PresentationSqlModel::id() const {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString PresentationSqlModel::title() const {
|
||||
return m_title;
|
||||
}
|
||||
|
||||
void PresentationSqlModel::setTitle(const QString &title) {
|
||||
if (title == m_title)
|
||||
return;
|
||||
|
||||
m_title = title;
|
||||
|
||||
select();
|
||||
emit titleChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the title from outside the delegate
|
||||
void PresentationSqlModel::updateTitle(const int &row, const QString &title) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from presentations");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("title", title);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit titleChanged();
|
||||
}
|
||||
|
||||
QUrl PresentationSqlModel::filePath() const {
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
void PresentationSqlModel::setFilePath(const QUrl &filePath) {
|
||||
if (filePath == m_filePath)
|
||||
return;
|
||||
|
||||
m_filePath = filePath;
|
||||
|
||||
select();
|
||||
emit filePathChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the filepath from outside the delegate
|
||||
void PresentationSqlModel::updateFilePath(const int &row, const QUrl &filePath) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from presentations");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("filePath", filePath);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit filePathChanged();
|
||||
}
|
||||
|
||||
QVariantMap PresentationSqlModel::getPresentation(const int &row) {
|
||||
// qDebug() << "Row we are getting is " << row;
|
||||
// QUrl presentation;
|
||||
// QSqlRecord rec = record(row);
|
||||
// qDebug() << rec.value("filePath").toUrl();
|
||||
// // presentation.append(rec.value("title"));
|
||||
// // presentation.append(rec.value("filePath"));
|
||||
// presentation = rec.value("filePath").toUrl();
|
||||
// return presentation;
|
||||
|
||||
QVariantMap data;
|
||||
const QModelIndex idx = this->index(row,0);
|
||||
// qDebug() << idx;
|
||||
if( !idx.isValid() )
|
||||
return data;
|
||||
const QHash<int,QByteArray> rn = roleNames();
|
||||
// qDebug() << rn;
|
||||
QHashIterator<int,QByteArray> it(rn);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
qDebug() << it.key() << ":" << it.value();
|
||||
data[it.value()] = idx.data(it.key());
|
||||
}
|
||||
return data;
|
||||
}
|
49
src/cpp/presentationsqlmodel.h
Normal file
49
src/cpp/presentationsqlmodel.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef PRESENTATIONSQLMODEL_H
|
||||
#define PRESENTATIONSQLMODEL_H
|
||||
|
||||
#include <QSqlTableModel>
|
||||
#include <qobject.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qqml.h>
|
||||
#include <qurl.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
class PresentationSqlModel : public QSqlTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int id READ id)
|
||||
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
|
||||
Q_PROPERTY(QUrl filePath READ filePath WRITE setFilePath NOTIFY filePathChanged)
|
||||
QML_ELEMENT
|
||||
|
||||
public:
|
||||
PresentationSqlModel(QObject *parent = 0);
|
||||
|
||||
int id() const;
|
||||
QString title() const;
|
||||
QUrl filePath() const;
|
||||
|
||||
void setTitle(const QString &title);
|
||||
void setFilePath(const QUrl &filePath);
|
||||
|
||||
Q_INVOKABLE void updateTitle(const int &row, const QString &title);
|
||||
Q_INVOKABLE void updateFilePath(const int &row, const QUrl &filePath);
|
||||
|
||||
Q_INVOKABLE void newPresentation(const QUrl &filePath);
|
||||
Q_INVOKABLE void deletePresentation(const int &row);
|
||||
Q_INVOKABLE QVariantMap getPresentation(const int &row);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
signals:
|
||||
void titleChanged();
|
||||
void filePathChanged();
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
QString m_title;
|
||||
QUrl m_filePath;
|
||||
};
|
||||
|
||||
#endif //PRESENTATIONSQLMODEL_H
|
186
src/cpp/serviceitem.cpp
Normal file
186
src/cpp/serviceitem.cpp
Normal file
|
@ -0,0 +1,186 @@
|
|||
#include "serviceitem.h"
|
||||
#include <QDebug>
|
||||
|
||||
ServiceItem::ServiceItem(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ServiceItem::ServiceItem(const QString &name, const QString &type, QObject *parent)
|
||||
: QObject(parent),m_name(name),m_type(type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ServiceItem::ServiceItem(const QString &name, const QString &type, const QString &background,
|
||||
const QString &backgroundType, QObject *parent)
|
||||
: QObject(parent),m_name(name),m_type(type),m_background(background),
|
||||
m_backgroundType(backgroundType)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ServiceItem::ServiceItem(const QString &name, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
QObject *parent)
|
||||
: QObject(parent),m_name(name),m_type(type),m_background(background),
|
||||
m_backgroundType(backgroundType),m_text(text)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ServiceItem::ServiceItem(const QString &name, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
const QString &audio, QObject *parent)
|
||||
: QObject(parent),m_name(name),m_type(type),m_background(background),
|
||||
m_backgroundType(backgroundType),m_text(text),m_audio(audio)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ServiceItem::ServiceItem(const QString &name, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
const QString &audio, const QString &font, const int &fontSize,
|
||||
QObject *parent)
|
||||
: QObject(parent),m_name(name),m_type(type),m_background(background),
|
||||
m_backgroundType(backgroundType),m_text(text),m_audio(audio),m_font(font),m_fontSize(fontSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString ServiceItem::name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
QString ServiceItem::type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
QString ServiceItem::background() const
|
||||
{
|
||||
return m_background;
|
||||
}
|
||||
|
||||
QString ServiceItem::backgroundType() const
|
||||
{
|
||||
return m_backgroundType;
|
||||
}
|
||||
|
||||
QStringList ServiceItem::text() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
QString ServiceItem::audio() const {
|
||||
return m_audio;
|
||||
}
|
||||
|
||||
QString ServiceItem::font() const {
|
||||
return m_font;
|
||||
}
|
||||
|
||||
int ServiceItem::fontSize() const {
|
||||
return m_fontSize;
|
||||
}
|
||||
|
||||
bool ServiceItem::active() const {
|
||||
return m_active;
|
||||
}
|
||||
|
||||
bool ServiceItem::selected() const {
|
||||
return m_selected;
|
||||
}
|
||||
|
||||
void ServiceItem::setName(QString name)
|
||||
{
|
||||
if (m_name == name)
|
||||
return;
|
||||
|
||||
m_name = name;
|
||||
emit nameChanged(m_name);
|
||||
}
|
||||
|
||||
void ServiceItem::setType(QString type)
|
||||
{
|
||||
if (m_type == type)
|
||||
return;
|
||||
|
||||
m_type = type;
|
||||
emit typeChanged(m_type);
|
||||
}
|
||||
|
||||
void ServiceItem::setBackground(QString background)
|
||||
{
|
||||
if (m_background == background)
|
||||
return;
|
||||
|
||||
m_background = background;
|
||||
emit backgroundChanged(m_background);
|
||||
}
|
||||
|
||||
void ServiceItem::setBackgroundType(QString backgroundType)
|
||||
{
|
||||
if (m_backgroundType == backgroundType)
|
||||
return;
|
||||
|
||||
m_backgroundType = backgroundType;
|
||||
emit backgroundTypeChanged(m_backgroundType);
|
||||
}
|
||||
|
||||
void ServiceItem::setText(QStringList text)
|
||||
{
|
||||
if (m_text == text)
|
||||
return;
|
||||
|
||||
m_text = text;
|
||||
emit textChanged(m_text);
|
||||
|
||||
}
|
||||
|
||||
void ServiceItem::setAudio(QString audio)
|
||||
{
|
||||
if (m_audio == audio)
|
||||
return;
|
||||
|
||||
m_audio = audio;
|
||||
emit audioChanged(m_audio);
|
||||
}
|
||||
|
||||
void ServiceItem::setFont(QString font)
|
||||
{
|
||||
if (m_font == font)
|
||||
return;
|
||||
|
||||
m_font = font;
|
||||
emit fontChanged(m_font);
|
||||
}
|
||||
|
||||
void ServiceItem::setFontSize(int fontSize)
|
||||
{
|
||||
if (m_fontSize == fontSize)
|
||||
return;
|
||||
|
||||
m_fontSize = fontSize;
|
||||
emit fontSizeChanged(m_fontSize);
|
||||
}
|
||||
|
||||
void ServiceItem::setActive(bool active)
|
||||
{
|
||||
qDebug() << "::::::::::::::::::::";
|
||||
qDebug() << "CHANGE ME!";
|
||||
if (m_active == active)
|
||||
return;
|
||||
|
||||
m_active = active;
|
||||
emit activeChanged(m_active);
|
||||
}
|
||||
|
||||
void ServiceItem::setSelected(bool selected)
|
||||
{
|
||||
if (m_selected == selected)
|
||||
return;
|
||||
|
||||
m_selected = selected;
|
||||
emit selectedChanged(m_selected);
|
||||
}
|
86
src/cpp/serviceitem.h
Normal file
86
src/cpp/serviceitem.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
#ifndef SERVICEITEM_H
|
||||
#define SERVICEITEM_H
|
||||
|
||||
#include <QObject>
|
||||
#include <qobject.h>
|
||||
#include "thumbnail.h"
|
||||
|
||||
class ServiceItem : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
|
||||
Q_PROPERTY(QString type READ type WRITE setType NOTIFY typeChanged)
|
||||
Q_PROPERTY(QString background READ background WRITE setBackground NOTIFY backgroundChanged)
|
||||
Q_PROPERTY(QString backgroundType READ backgroundType WRITE setBackgroundType NOTIFY backgroundTypeChanged)
|
||||
Q_PROPERTY(QStringList text READ text WRITE setText NOTIFY textChanged)
|
||||
Q_PROPERTY(QString audio READ audio WRITE setAudio NOTIFY audioChanged)
|
||||
Q_PROPERTY(QString font READ font WRITE setFont NOTIFY fontChanged)
|
||||
Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
|
||||
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
|
||||
Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged)
|
||||
// Q_PROPERTY(Thumbnail thumbnail READ thumbnail WRITE setThumbnail NOTIFY thumbnailChanged)
|
||||
|
||||
public:
|
||||
explicit ServiceItem(QObject *parent = nullptr);
|
||||
ServiceItem(const QString &name, const QString &type, QObject * parent = nullptr);
|
||||
ServiceItem(const QString &name, const QString &type, const QString &background,
|
||||
const QString &backgroundType, QObject * parent = nullptr);
|
||||
ServiceItem(const QString &name, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
QObject * parent = nullptr);
|
||||
ServiceItem(const QString &name, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text, const QString &audio,
|
||||
QObject * parent = nullptr);
|
||||
ServiceItem(const QString &name, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text, const QString &audio,
|
||||
const QString &font, const int &fontSize, QObject * parent = nullptr);
|
||||
|
||||
QString name() const;
|
||||
QString type() const;
|
||||
QString background() const;
|
||||
QString backgroundType() const;
|
||||
QStringList text() const;
|
||||
QString audio() const;
|
||||
QString font() const;
|
||||
int fontSize() const;
|
||||
bool active() const;
|
||||
bool selected() const;
|
||||
// Thumbnail thumbnail() const;
|
||||
|
||||
void setName(QString name);
|
||||
void setType(QString type);
|
||||
void setBackground(QString background);
|
||||
void setBackgroundType(QString backgroundType);
|
||||
void setText(QStringList text);
|
||||
void setAudio(QString audio);
|
||||
void setFont(QString font);
|
||||
void setFontSize(int fontSize);
|
||||
void setActive(bool active);
|
||||
void setSelected(bool selected);
|
||||
|
||||
signals:
|
||||
void nameChanged(QString name);
|
||||
void typeChanged(QString type);
|
||||
void backgroundChanged(QString background);
|
||||
void backgroundTypeChanged(QString backgroundType);
|
||||
void textChanged(QStringList text);
|
||||
void audioChanged(QString audio);
|
||||
void fontChanged(QString font);
|
||||
void fontSizeChanged(int fontSize);
|
||||
void activeChanged(bool active);
|
||||
void selectedChanged(bool selected);
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
QString m_type;
|
||||
QString m_background;
|
||||
QString m_backgroundType;
|
||||
QStringList m_text;
|
||||
QString m_audio;
|
||||
QString m_font;
|
||||
int m_fontSize;
|
||||
bool m_active;
|
||||
bool m_selected;
|
||||
};
|
||||
|
||||
#endif // SERVICEITEM_H
|
737
src/cpp/serviceitemmodel.cpp
Normal file
737
src/cpp/serviceitemmodel.cpp
Normal file
|
@ -0,0 +1,737 @@
|
|||
#include "serviceitemmodel.h"
|
||||
#include "serviceitem.h"
|
||||
#include "filemanager.h"
|
||||
#include <qabstractitemmodel.h>
|
||||
#include <qglobal.h>
|
||||
#include <qnamespace.h>
|
||||
#include <qvariant.h>
|
||||
#include <ktar.h>
|
||||
#include <KCompressionDevice>
|
||||
#include <KArchiveDirectory>
|
||||
#include <KArchiveFile>
|
||||
#include <KArchiveEntry>
|
||||
#include <QDebug>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QFile>
|
||||
#include <QMap>
|
||||
#include <QTemporaryFile>
|
||||
#include <QDir>
|
||||
#include <QUrl>
|
||||
#include <QSettings>
|
||||
#include <QStandardPaths>
|
||||
#include <QImage>
|
||||
|
||||
|
||||
ServiceItemModel::ServiceItemModel(QObject *parent)
|
||||
: QAbstractListModel(parent) {
|
||||
if (!loadLastSaved()) {
|
||||
addItem(new ServiceItem("10,000 Reasons", "song",
|
||||
"file:/home/chris/nextcloud/tfc/openlp/CMG - Nature King 21.jpg",
|
||||
"image", QStringList("Yip Yip"),
|
||||
"file:/home/chris/nextcloud/tfc/openlp/music/Eden-Phil Wickham [lyrics].mp3"));
|
||||
addItem(new ServiceItem("Marvelous Light", "song",
|
||||
"file:/home/chris/nextcloud/tfc/openlp/Fire Embers_Loop.mp4",
|
||||
"video", QStringList("Hallelujah!")));
|
||||
addItem(new ServiceItem("BP Text", "video",
|
||||
"file:/home/chris/nextcloud/tfc/openlp/videos/test.mp4",
|
||||
"video", QStringList()));
|
||||
}
|
||||
}
|
||||
|
||||
int ServiceItemModel::rowCount(const QModelIndex &parent) const {
|
||||
// For list models only the root node (an invalid parent) should return the
|
||||
// list's size. For all other (valid) parents, rowCount() should return 0 so
|
||||
// that it does not become a tree model.
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
|
||||
// FIXME: Implement me!
|
||||
return m_items.size();
|
||||
}
|
||||
|
||||
QVariant ServiceItemModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
ServiceItem *item = m_items[index.row()];
|
||||
switch (role) {
|
||||
case NameRole:
|
||||
return item->name();
|
||||
case TypeRole:
|
||||
return item->type();
|
||||
case BackgroundRole:
|
||||
return item->background();
|
||||
case BackgroundTypeRole:
|
||||
return item->backgroundType();
|
||||
case TextRole:
|
||||
return item->text();
|
||||
case AudioRole:
|
||||
return item->audio();
|
||||
case FontRole:
|
||||
return item->font();
|
||||
case FontSizeRole:
|
||||
return item->fontSize();
|
||||
case ActiveRole:
|
||||
return item->active();
|
||||
case SelectedRole:
|
||||
return item->selected();
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ServiceItemModel::roleNames() const {
|
||||
static QHash<int, QByteArray> mapping{{NameRole, "name"},
|
||||
{TypeRole, "type"},
|
||||
{BackgroundRole, "background"},
|
||||
{BackgroundTypeRole, "backgroundType"},
|
||||
{TextRole, "text"},
|
||||
{AudioRole, "audio"},
|
||||
{FontRole, "font"},
|
||||
{FontSizeRole, "fontSize"},
|
||||
{ActiveRole, "active"},
|
||||
{SelectedRole, "selected"}};
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
bool ServiceItemModel::setData(const QModelIndex &index, const QVariant &value,
|
||||
int role) {
|
||||
|
||||
ServiceItem *item = m_items[index.row()];
|
||||
bool somethingChanged = false;
|
||||
|
||||
switch (role) {
|
||||
case NameRole:
|
||||
if (item->name() != value.toString()) {
|
||||
item->setName(value.toString());
|
||||
somethingChanged = true;
|
||||
}
|
||||
break;
|
||||
case TypeRole:
|
||||
if (item->type() != value.toString()) {
|
||||
item->setType(value.toString());
|
||||
somethingChanged = true;
|
||||
}
|
||||
break;
|
||||
case BackgroundRole:
|
||||
if (item->background() != value.toString()) {
|
||||
item->setBackground(value.toString());
|
||||
somethingChanged = true;
|
||||
}
|
||||
break;
|
||||
case BackgroundTypeRole:
|
||||
if (item->backgroundType() != value.toString()) {
|
||||
item->setBackgroundType(value.toString());
|
||||
somethingChanged = true;
|
||||
}
|
||||
break;
|
||||
case TextRole:
|
||||
if (item->text() != value.toStringList()) {
|
||||
item->setText(value.toStringList());
|
||||
somethingChanged = true;
|
||||
}
|
||||
break;
|
||||
case AudioRole:
|
||||
if (item->audio() != value.toString()) {
|
||||
item->setAudio(value.toString());
|
||||
somethingChanged = true;
|
||||
}
|
||||
break;
|
||||
case FontRole:
|
||||
if (item->font() != value.toString()) {
|
||||
item->setFont(value.toString());
|
||||
somethingChanged = true;
|
||||
}
|
||||
break;
|
||||
case FontSizeRole:
|
||||
if (item->fontSize() != value.toInt()) {
|
||||
item->setFontSize(value.toInt());
|
||||
somethingChanged = true;
|
||||
}
|
||||
break;
|
||||
case ActiveRole:
|
||||
if (item->active() != value.toBool()) {
|
||||
item->setActive(value.toBool());
|
||||
somethingChanged = true;
|
||||
}
|
||||
break;
|
||||
case SelectedRole:
|
||||
if (item->selected() != value.toBool()) {
|
||||
item->setSelected(value.toBool());
|
||||
somethingChanged = true;
|
||||
}
|
||||
break;
|
||||
if (somethingChanged) {
|
||||
emit dataChanged(index, index, QVector<int>() << role);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ItemFlags ServiceItemModel::flags(const QModelIndex &index) const {
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
return Qt::ItemIsEditable; // FIXME: Implement me!
|
||||
}
|
||||
|
||||
// int ServiceItemModel::index(int row, int column, const QModelIndex &parent) {
|
||||
// if (!hasIndex(row, column, parent))
|
||||
// return QModelIndex();
|
||||
|
||||
// ServiceItem *parentItem;
|
||||
|
||||
// if (!parent.isValid())
|
||||
// parentItem = rootItem;
|
||||
// else
|
||||
// parentItem = static_cast<ServiceItem*>(parent.internalPointer());
|
||||
|
||||
// ServiceItem *childItem = parentItem->child(row);
|
||||
// if (childItem)
|
||||
// return createIndex(row, column, childItem);
|
||||
// return QModelIndex();
|
||||
// }
|
||||
|
||||
void ServiceItemModel::addItem(ServiceItem *item) {
|
||||
const int index = m_items.size();
|
||||
qDebug() << index;
|
||||
// foreach (item, m_items) {
|
||||
// qDebug() << item;
|
||||
// }
|
||||
beginInsertRows(QModelIndex(), index, index);
|
||||
m_items.append(item);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void ServiceItemModel::insertItem(const int &index, ServiceItem *item) {
|
||||
beginInsertRows(this->index(index).parent(), index, index);
|
||||
m_items.insert(index, item);
|
||||
endInsertRows();
|
||||
qDebug() << "Success";
|
||||
}
|
||||
|
||||
void ServiceItemModel::addItem(const QString &name, const QString &type) {
|
||||
ServiceItem *item = new ServiceItem(name, type);
|
||||
item->setSelected(false);
|
||||
item->setActive(false);
|
||||
addItem(item);
|
||||
}
|
||||
|
||||
void ServiceItemModel::addItem(const QString &name, const QString &type,
|
||||
const QString &background, const QString &backgroundType) {
|
||||
ServiceItem *item = new ServiceItem(name, type, background, backgroundType);
|
||||
item->setSelected(false);
|
||||
item->setActive(false);
|
||||
addItem(item);
|
||||
}
|
||||
|
||||
void ServiceItemModel::addItem(const QString &name, const QString &type,
|
||||
const QString &background, const QString &backgroundType,
|
||||
const QStringList &text) {
|
||||
ServiceItem *item = new ServiceItem(name, type, background, backgroundType, text);
|
||||
item->setSelected(false);
|
||||
item->setActive(false);
|
||||
addItem(item);
|
||||
qDebug() << name << type << background;
|
||||
}
|
||||
|
||||
void ServiceItemModel::addItem(const QString &name, const QString &type,
|
||||
const QString &background, const QString &backgroundType,
|
||||
const QStringList &text, const QString &audio) {
|
||||
ServiceItem *item = new ServiceItem(name, type, background, backgroundType,
|
||||
text, audio);
|
||||
item->setSelected(false);
|
||||
item->setActive(false);
|
||||
addItem(item);
|
||||
qDebug() << name << type << background;
|
||||
}
|
||||
|
||||
void ServiceItemModel::addItem(const QString &name, const QString &type,
|
||||
const QString &background, const QString &backgroundType,
|
||||
const QStringList &text, const QString &audio,
|
||||
const QString &font, const int &fontSize) {
|
||||
ServiceItem *item = new ServiceItem(name, type, background, backgroundType,
|
||||
text, audio, font, fontSize);
|
||||
item->setSelected(false);
|
||||
item->setActive(false);
|
||||
addItem(item);
|
||||
qDebug() << "#################################";
|
||||
qDebug() << name << type << font << fontSize;
|
||||
qDebug() << "#################################";
|
||||
}
|
||||
|
||||
void ServiceItemModel::insertItem(const int &index, const QString &name, const QString &type) {
|
||||
ServiceItem *item = new ServiceItem(name, type);
|
||||
item->setSelected(false);
|
||||
item->setActive(false);
|
||||
insertItem(index, item);
|
||||
qDebug() << name << type;
|
||||
}
|
||||
|
||||
void ServiceItemModel::insertItem(const int &index, const QString &name, const QString &type,
|
||||
const QString &background, const QString &backgroundType) {
|
||||
ServiceItem *item = new ServiceItem(name, type, background, backgroundType);
|
||||
item->setSelected(false);
|
||||
item->setActive(false);
|
||||
insertItem(index, item);
|
||||
qDebug() << name << type << background;
|
||||
}
|
||||
|
||||
void ServiceItemModel::insertItem(const int &index, const QString &name, const QString &type,
|
||||
const QString &background, const QString &backgroundType,
|
||||
const QStringList &text) {
|
||||
ServiceItem *item = new ServiceItem(name, type, background, backgroundType, text);
|
||||
insertItem(index, item);
|
||||
qDebug() << name << type << background << text;
|
||||
}
|
||||
|
||||
void ServiceItemModel::insertItem(const int &index, const QString &name,
|
||||
const QString &type,const QString &background,
|
||||
const QString &backgroundType,const QStringList &text,
|
||||
const QString &audio) {
|
||||
ServiceItem *item = new ServiceItem(name, type, background, backgroundType,
|
||||
text, audio);
|
||||
item->setSelected(false);
|
||||
item->setActive(false);
|
||||
insertItem(index, item);
|
||||
qDebug() << name << type << background << text;
|
||||
}
|
||||
|
||||
void ServiceItemModel::insertItem(const int &index, const QString &name,
|
||||
const QString &type,const QString &background,
|
||||
const QString &backgroundType,const QStringList &text,
|
||||
const QString &audio, const QString &font, const int &fontSize) {
|
||||
ServiceItem *item = new ServiceItem(name, type, background, backgroundType,
|
||||
text, audio, font, fontSize);
|
||||
item->setSelected(false);
|
||||
item->setActive(false);
|
||||
insertItem(index, item);
|
||||
qDebug() << "#################################";
|
||||
qDebug() << name << type << font << fontSize;
|
||||
qDebug() << "#################################";
|
||||
}
|
||||
|
||||
void ServiceItemModel::removeItem(int index) {
|
||||
beginRemoveRows(QModelIndex(), index, index);
|
||||
m_items.removeAt(index);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
bool ServiceItemModel::moveRows(int sourceIndex, int destIndex, int count) {
|
||||
qDebug() << index(sourceIndex).row();
|
||||
qDebug() << index(destIndex).row();
|
||||
|
||||
const int lastIndex = rowCount() - 1;
|
||||
|
||||
if (sourceIndex == destIndex
|
||||
|| (sourceIndex < 0 || sourceIndex > lastIndex)
|
||||
|| (destIndex < 0 || destIndex > lastIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const QModelIndex parent = index(sourceIndex).parent();
|
||||
const bool isMoveDown = destIndex > sourceIndex;
|
||||
|
||||
if (!beginMoveRows(parent, sourceIndex, sourceIndex + count - 1,
|
||||
parent, isMoveDown ? destIndex + 1 : destIndex)) {
|
||||
qDebug() << "Can't move rows";
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "starting move: " << "source: " << sourceIndex << "dest: " << destIndex;
|
||||
|
||||
m_items.move(sourceIndex, isMoveDown ? destIndex + 1 : destIndex);
|
||||
|
||||
endMoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceItemModel::moveDown(int id) {
|
||||
qDebug() << index(id).row();
|
||||
qDebug() << index(id + 1).row();
|
||||
QModelIndex parent = index(id).parent();
|
||||
|
||||
bool begsuc = beginMoveRows(parent, id,
|
||||
id, parent, id + 2);
|
||||
if (begsuc) {
|
||||
int dest = id + 1;
|
||||
if (dest >= m_items.size())
|
||||
{
|
||||
qDebug() << "dest too big, moving to end";
|
||||
m_items.move(id, m_items.size() - 1);
|
||||
}
|
||||
else
|
||||
m_items.move(id, dest);
|
||||
endMoveRows();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ServiceItemModel::moveUp(int id) {
|
||||
qDebug() << index(id).row();
|
||||
qDebug() << index(id - 1).row();
|
||||
QModelIndex parent = index(id).parent();
|
||||
|
||||
bool begsuc = beginMoveRows(parent, id,
|
||||
id, parent, id - 1);
|
||||
if (begsuc) {
|
||||
int dest = id - 1;
|
||||
if (dest <= -1)
|
||||
{
|
||||
qDebug() << "dest too big, moving to beginning";
|
||||
m_items.move(id, 0);
|
||||
}
|
||||
else
|
||||
m_items.move(id, dest);
|
||||
endMoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariantMap ServiceItemModel::getItem(int index) const {
|
||||
QVariantMap data;
|
||||
const QModelIndex idx = this->index(index,0);
|
||||
// qDebug() << idx;
|
||||
if( !idx.isValid() )
|
||||
return data;
|
||||
const QHash<int,QByteArray> rn = roleNames();
|
||||
// qDebug() << rn;
|
||||
QHashIterator<int,QByteArray> it(rn);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
qDebug() << it.key() << ":" << it.value();
|
||||
data[it.value()] = idx.data(it.key());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
QVariantList ServiceItemModel::getItems() {
|
||||
QVariantList data;
|
||||
ServiceItem * item;
|
||||
foreach (item, m_items) {
|
||||
qDebug() << item->name();
|
||||
QVariantMap itm;
|
||||
itm["name"] = item->name();
|
||||
itm["type"] = item->type();
|
||||
itm["background"] = item->background();
|
||||
itm["backgroundType"] = item->backgroundType();
|
||||
itm["text"] = item->text();
|
||||
itm["audio"] = item->audio();
|
||||
itm["font"] = item->font();
|
||||
itm["fontSize"] = item->fontSize();
|
||||
itm["selected"] = item->selected();
|
||||
itm["active"] = item->active();
|
||||
data.append(itm);
|
||||
}
|
||||
qDebug() << "$$$$$$$$$$$$$$$$$$$$$$$$$$$";
|
||||
qDebug() << data;
|
||||
qDebug() << "$$$$$$$$$$$$$$$$$$$$$$$$$$$";
|
||||
return data;
|
||||
}
|
||||
|
||||
bool ServiceItemModel::select(int id) {
|
||||
for (int i = 0; i < m_items.length(); i++) {
|
||||
QModelIndex idx = index(i);
|
||||
ServiceItem *item = m_items[idx.row()];
|
||||
if (item->selected()) {
|
||||
item->setSelected(false);
|
||||
qDebug() << "################";
|
||||
qDebug() << "deselected" << item->name();
|
||||
qDebug() << "################";
|
||||
emit dataChanged(idx, idx, QVector<int>() << SelectedRole);
|
||||
}
|
||||
}
|
||||
QModelIndex idx = index(id);
|
||||
ServiceItem *item = m_items[idx.row()];
|
||||
item->setSelected(true);
|
||||
qDebug() << "################";
|
||||
qDebug() << "selected" << item->name();
|
||||
qDebug() << "################";
|
||||
emit dataChanged(idx, idx, QVector<int>() << SelectedRole);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceItemModel::activate(int id) {
|
||||
QModelIndex idx = index(id);
|
||||
ServiceItem *item = m_items[idx.row()];
|
||||
|
||||
for (int i = 0; i < m_items.length(); i++) {
|
||||
QModelIndex idx = index(i);
|
||||
ServiceItem *itm = m_items[idx.row()];
|
||||
if (itm->active()) {
|
||||
itm->setActive(false);
|
||||
qDebug() << "################";
|
||||
qDebug() << "deactivated" << itm->name();
|
||||
qDebug() << "################";
|
||||
emit dataChanged(idx, idx, QVector<int>() << ActiveRole);
|
||||
}
|
||||
}
|
||||
|
||||
item->setActive(true);
|
||||
qDebug() << "################";
|
||||
qDebug() << "activated" << item->name();
|
||||
qDebug() << "################";
|
||||
emit dataChanged(idx, idx, QVector<int>() << ActiveRole);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceItemModel::deactivate(int id) {
|
||||
QModelIndex idx = index(id);
|
||||
ServiceItem *item = m_items[idx.row()];
|
||||
|
||||
item->setActive(false);
|
||||
qDebug() << "################";
|
||||
qDebug() << "deactivated" << item->name();
|
||||
qDebug() << "################";
|
||||
emit dataChanged(idx, idx, QVector<int>() << ActiveRole);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServiceItemModel::save(QUrl file) {
|
||||
qDebug() << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
|
||||
qDebug() << "Saving...";
|
||||
qDebug() << "File path is: " << file.toString();
|
||||
qDebug() << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
|
||||
|
||||
//first we'll get a json representation of our serviceList
|
||||
//save that to a temp file in case we need it but also convert
|
||||
//it to a byte array just before putting it into the archive
|
||||
|
||||
QJsonArray jsonData;
|
||||
|
||||
// save all the data and files in jsonData as just the base name
|
||||
// so that they are properly mapped in the resulting archive
|
||||
for (int i = 0; i < m_items.length(); i++) {
|
||||
// qDebug() << serviceList[i];
|
||||
QMap<QString, QVariant> item;
|
||||
qDebug() << m_items[i]->name();
|
||||
|
||||
item.insert("name", m_items[i]->name());
|
||||
item.insert("background", m_items[i]->background());
|
||||
item.insert("backgroundType", m_items[i]->backgroundType());
|
||||
item.insert("audio", m_items[i]->audio());
|
||||
item.insert("font", m_items[i]->font());
|
||||
item.insert("fontSize", m_items[i]->fontSize());
|
||||
item.insert("text", m_items[i]->text());
|
||||
item.insert("type", m_items[i]->type());
|
||||
|
||||
qDebug() << "AUDIO IS: " << item.value("audio").toString();
|
||||
QFileInfo audioFile = item.value("audio").toString();
|
||||
qDebug() << audioFile.fileName();
|
||||
item["flatAudio"] = audioFile.fileName();
|
||||
qDebug() << "AUDIO IS NOW: " << item.value("audio").toString();
|
||||
|
||||
QFileInfo backgroundFile = item.value("background").toString();
|
||||
item["flatBackground"] = backgroundFile.fileName();
|
||||
qDebug() << "BACKGRUOND IS: " << item.value("background").toString();
|
||||
// qDebug() << serviceList[i].value();
|
||||
QJsonObject obj = QJsonObject::fromVariantMap(item);
|
||||
qDebug() << obj;
|
||||
jsonData.insert(i, obj);
|
||||
}
|
||||
|
||||
qDebug() << jsonData;
|
||||
QJsonDocument jsonText(jsonData);
|
||||
QTemporaryFile jsonFile;
|
||||
|
||||
if (!jsonFile.exists())
|
||||
qDebug() << "NOT EXISTS!";
|
||||
|
||||
if (!jsonFile.open())
|
||||
return false;
|
||||
|
||||
//finalize the temp json file, in case something goes wrong in the
|
||||
//archive, we'll have this to jump back to
|
||||
jsonFile.write(jsonText.toJson());
|
||||
qDebug() << jsonFile.fileName();
|
||||
jsonFile.close();
|
||||
|
||||
//now we create our archive file and set it's parameters
|
||||
QString filename = file.toString().right(file.toString().size() - 7);
|
||||
qDebug() << filename;
|
||||
|
||||
QString tarname;
|
||||
if (filename.endsWith(".pres")) {
|
||||
qDebug() << "Perfect just go with it!";
|
||||
tarname = filename;
|
||||
} else
|
||||
tarname = filename + ".pres";
|
||||
|
||||
KTar tar(tarname, "application/zstd");
|
||||
|
||||
if (tar.open(QIODevice::WriteOnly)) {
|
||||
qDebug() << tar.isOpen();
|
||||
|
||||
//write our json data to the archive
|
||||
tar.writeFile("servicelist.json",
|
||||
jsonText.toJson());
|
||||
|
||||
//let's add the backgrounds and audios to the archive
|
||||
for (int i = 0; i < m_items.size(); i++) {
|
||||
qDebug() << m_items[i]->name();
|
||||
QString background = m_items[i]->background();
|
||||
QString backgroundFile = background.right(background.size() - 5);
|
||||
qDebug() << backgroundFile;
|
||||
QString audio = m_items[i]->audio();
|
||||
QString audioFile = audio.right(audio.size() - 5);
|
||||
qDebug() << audioFile;
|
||||
|
||||
//here we need to cut off all the directories before
|
||||
//adding into the archive
|
||||
tar.addLocalFile(backgroundFile,
|
||||
backgroundFile.right(backgroundFile.size() -
|
||||
backgroundFile.lastIndexOf("/") - 1));
|
||||
tar.addLocalFile(audioFile,
|
||||
audioFile.right(audioFile.size() -
|
||||
audioFile.lastIndexOf("/") - 1));
|
||||
}
|
||||
|
||||
//close the archive so that everything is done
|
||||
tar.close();
|
||||
|
||||
QSettings settings;
|
||||
settings.setValue("lastSaveFile", file);
|
||||
|
||||
settings.sync();
|
||||
|
||||
qDebug() << settings.value("lastSaveFile");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ServiceItemModel::load(QUrl file) {
|
||||
qDebug() << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
|
||||
qDebug() << "Loading...";
|
||||
qDebug() << "File path is: " << file.toString();
|
||||
qDebug() << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
|
||||
|
||||
|
||||
QString fileUrl = file.toString().right(file.toString().size() - 7);
|
||||
KTar tar(fileUrl);
|
||||
|
||||
if (tar.open(QIODevice::ReadOnly)){
|
||||
qDebug() << tar.isOpen();
|
||||
const KArchiveDirectory *dir = tar.directory();
|
||||
|
||||
const KArchiveEntry *e = dir->entry("servicelist.json");
|
||||
if (!e) {
|
||||
qDebug() << "File not found!";
|
||||
}
|
||||
const KArchiveFile *f = static_cast<const KArchiveFile *>(e);
|
||||
QByteArray arr(f->data());
|
||||
QJsonDocument jsonText = QJsonDocument::fromJson(arr);
|
||||
qDebug() << jsonText; // the file contents
|
||||
|
||||
QJsonArray array = jsonText.array();
|
||||
|
||||
QVariantList serviceList = array.toVariantList();
|
||||
qDebug() << serviceList;
|
||||
|
||||
// now lets remove all items from current list and add loaded ones
|
||||
clearAll();
|
||||
|
||||
for (int i = 0; i < serviceList.length(); i++) {
|
||||
// int id = serviceList
|
||||
qDebug() << "*********************************";
|
||||
qDebug() << serviceList[i].toMap();
|
||||
qDebug() << "*********************************";
|
||||
|
||||
QMap item = serviceList[i].toMap();
|
||||
|
||||
QString backgroundString = item.value("background").toString();
|
||||
QFileInfo backgroundFile = backgroundString.right(backgroundString.size() - 7);
|
||||
|
||||
QString audioString = item.value("audio").toString();
|
||||
QFileInfo audioFile = audioString.right(audioString.size() - 7);
|
||||
|
||||
qDebug() << "POOPPOPOPOPOPOPOPOPOPOPOPOPO";
|
||||
qDebug() << backgroundFile;
|
||||
qDebug() << backgroundFile.exists();
|
||||
qDebug() << audioFile;
|
||||
qDebug() << audioFile.exists();
|
||||
qDebug() << "POOPPOPOPOPOPOPOPOPOPOPOPOPO";
|
||||
|
||||
QString realBackground;
|
||||
QString realAudio;
|
||||
|
||||
QFileInfo serviceFile = file.toString().right(file.toString().size() - 7);
|
||||
QString serviceName = serviceFile.baseName();
|
||||
QDir localDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
localDir.mkdir(serviceName);
|
||||
QDir serviceDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)
|
||||
+ "/" + serviceName;
|
||||
qDebug() << serviceDir.path();
|
||||
|
||||
realBackground = backgroundString;
|
||||
realAudio = audioString;
|
||||
// If the background file is on disk use that, else use the one in archive
|
||||
if (!backgroundFile.exists() && backgroundString.length() > 0) {
|
||||
const KArchiveEntry *e = dir->entry(backgroundFile.fileName());
|
||||
if (!e) {
|
||||
qDebug() << "Background File not found!";
|
||||
continue;
|
||||
}
|
||||
const KArchiveFile *f = static_cast<const KArchiveFile *>(e);
|
||||
if (!f->copyTo(serviceDir.path()))
|
||||
qDebug() << "FILE COULDN'T BE CREATED!";
|
||||
|
||||
QFileInfo bgFile = serviceDir.path() + "/" + backgroundFile.fileName();
|
||||
|
||||
qDebug() << bgFile.filePath();
|
||||
|
||||
realBackground = bgFile.filePath();
|
||||
}
|
||||
|
||||
// If the audio file is on disk use that, else use the one in archive
|
||||
if (!audioFile.exists() && audioString.length() > 0) {
|
||||
const KArchiveEntry *e = dir->entry(audioFile.fileName());
|
||||
if (!e) {
|
||||
qDebug() << "Audio File not found!";
|
||||
continue;
|
||||
}
|
||||
const KArchiveFile *f = static_cast<const KArchiveFile *>(e);
|
||||
if (!f->copyTo(serviceDir.path()))
|
||||
qDebug() << "FILE COULDN'T BE CREATED!";
|
||||
|
||||
QFileInfo audFile = serviceDir.path() + "/" + audioFile.fileName();
|
||||
|
||||
qDebug() << audFile.filePath();
|
||||
|
||||
realAudio = audFile.filePath();
|
||||
}
|
||||
|
||||
insertItem(i, item.value("name").toString(), item.value("type").toString(),
|
||||
realBackground,
|
||||
item.value("backgroundType").toString(),
|
||||
item.value("text").toStringList(), realAudio,
|
||||
item.value("font").toString(), item.value("fontSize").toInt());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ServiceItemModel::clearAll() {
|
||||
for (int i = m_items.size(); i >= 0; i--) {
|
||||
removeItem(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool ServiceItemModel::loadLastSaved() {
|
||||
QSettings settings;
|
||||
return load(settings.value("lastSaveFile").toUrl());
|
||||
}
|
103
src/cpp/serviceitemmodel.h
Normal file
103
src/cpp/serviceitemmodel.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
#ifndef SERVICEITEMMODEL_H
|
||||
#define SERVICEITEMMODEL_H
|
||||
|
||||
#include "serviceitem.h"
|
||||
#include <QAbstractListModel>
|
||||
#include <qabstractitemmodel.h>
|
||||
#include <qnamespace.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qsize.h>
|
||||
|
||||
class ServiceItemModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ServiceItemModel(QObject *parent = nullptr);
|
||||
|
||||
enum Roles {
|
||||
NameRole = Qt::UserRole,
|
||||
TypeRole,
|
||||
BackgroundRole,
|
||||
BackgroundTypeRole,
|
||||
TextRole,
|
||||
AudioRole,
|
||||
FontRole,
|
||||
FontSizeRole,
|
||||
ActiveRole,
|
||||
SelectedRole
|
||||
};
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
// int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
// Q_INVOKABLE int index(int row, int column,
|
||||
// const QModelIndex &parent = QModelIndex()) const override;
|
||||
// Q_INVOKABLE QModelIndex parent(const QModelIndex &index) const override;
|
||||
|
||||
// Editable:
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole) override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
// Helper methods
|
||||
void addItem(ServiceItem *item);
|
||||
void insertItem(const int &index, ServiceItem *item);
|
||||
Q_INVOKABLE void addItem(const QString &name, const QString &type);
|
||||
// Q_INVOKABLE void addItem(const QString &name, const QString &type,
|
||||
// const QString &background);
|
||||
Q_INVOKABLE void addItem(const QString &name, const QString &type,
|
||||
const QString &background,
|
||||
const QString &backgroundType);
|
||||
Q_INVOKABLE void addItem(const QString &name, const QString &type,
|
||||
const QString &background,
|
||||
const QString &backgroundType,
|
||||
const QStringList &text);
|
||||
Q_INVOKABLE void addItem(const QString &name, const QString &type,
|
||||
const QString &background,
|
||||
const QString &backgroundType,
|
||||
const QStringList &text, const QString &audio);
|
||||
Q_INVOKABLE void addItem(const QString &name, const QString &type,
|
||||
const QString &background,
|
||||
const QString &backgroundType,
|
||||
const QStringList &text, const QString &audio,
|
||||
const QString &font, const int &fontSize);
|
||||
Q_INVOKABLE void insertItem(const int &index, const QString &name,
|
||||
const QString &type);
|
||||
Q_INVOKABLE void insertItem(const int &index, const QString &name,
|
||||
const QString &type, const QString &background,
|
||||
const QString &backgroundType);
|
||||
Q_INVOKABLE void insertItem(const int &index, const QString &name,
|
||||
const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text);
|
||||
Q_INVOKABLE void insertItem(const int &index, const QString &name,
|
||||
const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
const QString &audio);
|
||||
Q_INVOKABLE void insertItem(const int &index, const QString &name,
|
||||
const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
const QString &audio, const QString &font, const int &fontSize);
|
||||
Q_INVOKABLE void removeItem(int index);
|
||||
Q_INVOKABLE bool moveRows(int sourceIndex, int destIndex, int count);
|
||||
Q_INVOKABLE bool moveDown(int index);
|
||||
Q_INVOKABLE bool moveUp(int index);
|
||||
Q_INVOKABLE bool select(int id);
|
||||
Q_INVOKABLE bool activate(int id);
|
||||
Q_INVOKABLE bool deactivate(int id);
|
||||
Q_INVOKABLE QVariantMap getItem(int index) const;
|
||||
Q_INVOKABLE QVariantList getItems();
|
||||
Q_INVOKABLE void clearAll();
|
||||
|
||||
Q_INVOKABLE bool save(QUrl file);
|
||||
Q_INVOKABLE bool load(QUrl file);
|
||||
Q_INVOKABLE bool loadLastSaved();
|
||||
|
||||
private:
|
||||
QList<ServiceItem *> m_items;
|
||||
};
|
||||
|
||||
#endif // SERVICEITEMMODEL_H
|
343
src/cpp/slide.cpp
Normal file
343
src/cpp/slide.cpp
Normal file
|
@ -0,0 +1,343 @@
|
|||
#include "slide.h"
|
||||
#include "serviceitemmodel.h"
|
||||
|
||||
#include <podofo/podofo.h>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace PoDoFo;
|
||||
Slide::Slide(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
qDebug() << "Initializing slide";
|
||||
}
|
||||
|
||||
Slide::Slide(const QString &text, const QString &audio, const QString &imageBackground,
|
||||
const QString &videoBackground, const QString &horizontalTextAlignment,
|
||||
const QString &verticalTextAlignment, const QString &font,
|
||||
const int &fontSize, const int &imageCount, const int &pdfIndex,
|
||||
const bool &isPlaying, const QString &type, QObject *parent)
|
||||
: QObject(parent),m_text(text),m_audio(audio),m_imageBackground(imageBackground),
|
||||
m_videoBackground(videoBackground),m_verticalTextAlignment(verticalTextAlignment),
|
||||
m_horizontalTextAlignment(horizontalTextAlignment),m_font(font),
|
||||
m_fontSize(fontSize),m_imageCount(imageCount),m_pdfIndex(pdfIndex),
|
||||
m_isPlaying(isPlaying),m_type(type)
|
||||
{
|
||||
qDebug() << "Initializing slide with defaults";
|
||||
}
|
||||
|
||||
QString Slide::text() const {
|
||||
return m_text;
|
||||
}
|
||||
|
||||
QString Slide::type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
QVariantMap Slide::serviceItem() const {
|
||||
return m_serviceItem;
|
||||
}
|
||||
|
||||
QString Slide::audio() const {
|
||||
return m_audio;
|
||||
}
|
||||
|
||||
QString Slide::imageBackground() const
|
||||
{
|
||||
return m_imageBackground;
|
||||
}
|
||||
|
||||
QString Slide::videoBackground() const
|
||||
{
|
||||
return m_videoBackground;
|
||||
}
|
||||
|
||||
QString Slide::horizontalTextAlignment() const
|
||||
{
|
||||
return m_horizontalTextAlignment;
|
||||
}
|
||||
|
||||
QString Slide::verticalTextAlignment() const
|
||||
{
|
||||
return m_verticalTextAlignment;
|
||||
}
|
||||
|
||||
QString Slide::font() const
|
||||
{
|
||||
return m_font;
|
||||
}
|
||||
|
||||
int Slide::fontSize() const
|
||||
{
|
||||
return m_fontSize;
|
||||
}
|
||||
|
||||
int Slide::imageCount() const
|
||||
{
|
||||
return m_imageCount;
|
||||
}
|
||||
|
||||
int Slide::pdfIndex() const
|
||||
{
|
||||
return m_pdfIndex;
|
||||
}
|
||||
|
||||
bool Slide::isPlaying() const
|
||||
{
|
||||
return m_isPlaying;
|
||||
}
|
||||
|
||||
void Slide::setText(QString text)
|
||||
{
|
||||
if (m_text == text)
|
||||
return;
|
||||
|
||||
qDebug() << "####changing text to: " << text;
|
||||
m_text = text;
|
||||
emit textChanged(m_text);
|
||||
}
|
||||
|
||||
void Slide::setType(QString type)
|
||||
{
|
||||
if (m_type == type)
|
||||
return;
|
||||
|
||||
qDebug() << "####changing type to: " << type;
|
||||
m_type = type;
|
||||
emit typeChanged(m_type);
|
||||
}
|
||||
|
||||
void Slide::setServiceItem(QVariantMap serviceItem)
|
||||
{
|
||||
if (m_serviceItem == serviceItem)
|
||||
return;
|
||||
|
||||
qDebug() << "####changing serviceItem to: " << serviceItem;
|
||||
m_serviceItem = serviceItem;
|
||||
emit serviceItemChanged(m_serviceItem);
|
||||
}
|
||||
|
||||
void Slide::setAudio(QString audio)
|
||||
{
|
||||
if (m_audio == audio)
|
||||
return;
|
||||
|
||||
qDebug() << "####changing audio to: " << audio;
|
||||
m_audio = audio;
|
||||
emit audioChanged(m_audio);
|
||||
}
|
||||
|
||||
void Slide::setImageBackground(QString imageBackground)
|
||||
{
|
||||
if (m_imageBackground == imageBackground)
|
||||
return;
|
||||
|
||||
qDebug() << "####changing image background to: " << imageBackground;
|
||||
m_imageBackground = imageBackground;
|
||||
emit imageBackgroundChanged(m_imageBackground);
|
||||
}
|
||||
|
||||
void Slide::setVideoBackground(QString videoBackground)
|
||||
{
|
||||
if (m_videoBackground == videoBackground)
|
||||
return;
|
||||
|
||||
qDebug() << "####changing video background to: " << videoBackground;
|
||||
m_videoBackground = videoBackground;
|
||||
emit videoBackgroundChanged(m_videoBackground);
|
||||
}
|
||||
|
||||
void Slide::setHorizontalTextAlignment(QString horizontalTextAlignment)
|
||||
{
|
||||
if (m_horizontalTextAlignment == horizontalTextAlignment)
|
||||
return;
|
||||
|
||||
m_horizontalTextAlignment = horizontalTextAlignment;
|
||||
emit horizontalTextAlignmentChanged(m_horizontalTextAlignment);
|
||||
}
|
||||
|
||||
void Slide::setVerticalTextAlignment(QString verticalTextAlignment)
|
||||
{
|
||||
if (m_verticalTextAlignment == verticalTextAlignment)
|
||||
return;
|
||||
|
||||
m_verticalTextAlignment = verticalTextAlignment;
|
||||
emit verticalTextAlignmentChanged(m_verticalTextAlignment);
|
||||
}
|
||||
|
||||
void Slide::setFont(QString font)
|
||||
{
|
||||
if (m_font == font)
|
||||
return;
|
||||
|
||||
m_font = font;
|
||||
emit fontChanged(m_font);
|
||||
}
|
||||
|
||||
void Slide::setFontSize(int fontSize)
|
||||
{
|
||||
if (m_fontSize == fontSize)
|
||||
return;
|
||||
|
||||
m_fontSize = fontSize;
|
||||
emit fontSizeChanged(m_fontSize);
|
||||
}
|
||||
|
||||
void Slide::setImageCount(int imageCount)
|
||||
{
|
||||
if (m_imageCount == imageCount)
|
||||
return;
|
||||
|
||||
qDebug() << "####changing imageCount to: " << imageCount;
|
||||
m_imageCount = imageCount;
|
||||
emit imageCountChanged(m_imageCount);
|
||||
}
|
||||
|
||||
void Slide::setPdfIndex(int pdfIndex)
|
||||
{
|
||||
if (m_pdfIndex == pdfIndex)
|
||||
return;
|
||||
|
||||
qDebug() << "####changing pdfIndex to: " << pdfIndex;
|
||||
m_pdfIndex = pdfIndex;
|
||||
emit pdfIndexChanged(m_pdfIndex);
|
||||
}
|
||||
|
||||
void Slide::changeSlide(QVariantMap item)
|
||||
{
|
||||
setServiceItem(item);
|
||||
setType(m_serviceItem.value("type").toString());
|
||||
qDebug() << "#$% SLIDE TYPE: " << type() << " %$#";
|
||||
|
||||
// First let's clear the text and then set
|
||||
// the size and index of a basic slide
|
||||
// then we'll build the rest
|
||||
setText("");
|
||||
m_slideSize = 1;
|
||||
m_slideIndex = 1;
|
||||
setPdfIndex(0);
|
||||
|
||||
qDebug() << serviceItem().value("backgroundType").toString();
|
||||
if (serviceItem().value("backgroundType") == "image") {
|
||||
setImageBackground(m_serviceItem.value("background").toString());
|
||||
setVideoBackground("");
|
||||
} else {
|
||||
setVideoBackground(m_serviceItem.value("background").toString());
|
||||
setImageBackground("");
|
||||
}
|
||||
|
||||
setFont(m_serviceItem.value("font").toString());
|
||||
setFontSize(m_serviceItem.value("fontSize").toInt());
|
||||
setAudio("");
|
||||
|
||||
if (type() == "presentation") {
|
||||
qDebug() << "#$#$#$#$ THIS PDF $#$#$#$#";
|
||||
int pageCount;
|
||||
QString str = imageBackground().remove(0,6);
|
||||
qDebug() << str;
|
||||
std::string file = str.toStdString();
|
||||
// qDebug() << file;
|
||||
const char * doc = file.c_str();
|
||||
qDebug() << doc;
|
||||
try {
|
||||
PdfMemDocument pdf = PdfMemDocument(doc);
|
||||
pageCount = pdf.GetPageCount();
|
||||
} catch ( const PdfError & eCode ) {
|
||||
eCode.PrintErrorMsg();
|
||||
eCode.GetError();
|
||||
return;
|
||||
}
|
||||
setImageCount(pageCount);
|
||||
qDebug() << m_imageCount;
|
||||
m_slideSize = m_imageCount;
|
||||
}
|
||||
|
||||
QStringList text = m_serviceItem.value("text").toStringList();
|
||||
if (type() == "song") {
|
||||
qDebug() << "TEXT LENGTH: " << text.length();
|
||||
m_slideSize = text.length();
|
||||
m_slideIndex = 1;
|
||||
setText(text[0]);
|
||||
setAudio(serviceItem().value("audio").toString());
|
||||
}
|
||||
|
||||
qDebug() << "MAP: " << m_serviceItem.value("text");
|
||||
}
|
||||
|
||||
bool Slide::next(QVariantMap nextItem)
|
||||
{
|
||||
qDebug() << "Starting to go to next item.";
|
||||
qDebug() << "Slide Index: " << m_slideIndex << " Slide Size: " << m_slideSize;
|
||||
QStringList text = m_serviceItem.value("text").toStringList();
|
||||
if (m_slideIndex == m_slideSize) {
|
||||
// changeSlide(nextItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
qDebug() << m_type;
|
||||
// since the string list is 0 indexed m_slideIndex actually
|
||||
// maps to the next item.
|
||||
if (m_type == "song") {
|
||||
int nextTextIndex = m_slideIndex;
|
||||
qDebug() << nextTextIndex;
|
||||
qDebug() << text[nextTextIndex];
|
||||
setText(text[nextTextIndex]);
|
||||
m_slideIndex++;
|
||||
}
|
||||
|
||||
if (m_type == "presentation") {
|
||||
qDebug() << "prev slide index: " << m_pdfIndex;
|
||||
setPdfIndex(m_pdfIndex + 1);
|
||||
qDebug() << "new slide index: " << m_pdfIndex;
|
||||
m_slideIndex++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Slide::previous(QVariantMap prevItem)
|
||||
{
|
||||
qDebug() << "Starting to go to previous item.";
|
||||
qDebug() << "Slide Index: " << m_slideIndex << " Slide Size: " << m_slideSize;
|
||||
QStringList text = m_serviceItem.value("text").toStringList();
|
||||
if (m_slideIndex == 1) {
|
||||
// changeSlide(prevItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
// since the string list is 0 indexed m_slideIndex actually
|
||||
// maps to the next item. So the prev text is minus 2
|
||||
if (m_type == "song") {
|
||||
int prevTextIndex = m_slideIndex - 2;
|
||||
qDebug() << prevTextIndex;
|
||||
qDebug() << text[prevTextIndex];
|
||||
setText(text[prevTextIndex]);
|
||||
m_slideIndex--;
|
||||
}
|
||||
|
||||
if (m_type == "presentation") {
|
||||
qDebug() << "prev slide index: " << m_pdfIndex;
|
||||
setPdfIndex(m_pdfIndex - 1);
|
||||
qDebug() << "new slide index: " << m_pdfIndex;
|
||||
m_slideIndex--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Slide::play()
|
||||
{
|
||||
m_isPlaying = true;
|
||||
emit isPlayingChanged(m_isPlaying);
|
||||
}
|
||||
|
||||
void Slide::pause()
|
||||
{
|
||||
m_isPlaying = false;
|
||||
emit isPlayingChanged(m_isPlaying);
|
||||
}
|
||||
|
||||
void Slide::playPause()
|
||||
{
|
||||
m_isPlaying = !m_isPlaying;
|
||||
emit isPlayingChanged(m_isPlaying);
|
||||
}
|
109
src/cpp/slide.h
Normal file
109
src/cpp/slide.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
#ifndef SLIDE_H
|
||||
#define SLIDE_H
|
||||
|
||||
#include <qobjectdefs.h>
|
||||
#include <qqml.h>
|
||||
#include <QObject>
|
||||
#include <qobject.h>
|
||||
|
||||
class Slide : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
|
||||
Q_PROPERTY(QString type READ type WRITE setType NOTIFY typeChanged)
|
||||
Q_PROPERTY(QVariantMap serviceItem READ serviceItem WRITE setServiceItem
|
||||
NOTIFY serviceItemChanged)
|
||||
Q_PROPERTY(QString audio READ audio WRITE setAudio NOTIFY audioChanged)
|
||||
Q_PROPERTY(QString imageBackground READ imageBackground WRITE setImageBackground
|
||||
NOTIFY imageBackgroundChanged)
|
||||
Q_PROPERTY(QString videoBackground READ videoBackground WRITE setVideoBackground
|
||||
NOTIFY videoBackgroundChanged)
|
||||
Q_PROPERTY(QString horizontalTextAlignment READ horizontalTextAlignment
|
||||
WRITE setHorizontalTextAlignment NOTIFY horizontalTextAlignmentChanged)
|
||||
Q_PROPERTY(QString verticalTextAlignment READ verticalTextAlignment
|
||||
WRITE setVerticalTextAlignment NOTIFY verticalTextAlignmentChanged)
|
||||
Q_PROPERTY(QString font READ font WRITE setFont NOTIFY fontChanged)
|
||||
Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
|
||||
Q_PROPERTY(int imageCount READ imageCount WRITE setImageCount NOTIFY imageCountChanged)
|
||||
Q_PROPERTY(int pdfIndex READ pdfIndex WRITE setPdfIndex NOTIFY pdfIndexChanged)
|
||||
Q_PROPERTY(bool isPlaying READ isPlaying NOTIFY isPlayingChanged)
|
||||
// QML_ELEMENT
|
||||
|
||||
public:
|
||||
explicit Slide(QObject *parent = nullptr);
|
||||
Slide(const QString &text, const QString &audio, const QString &imageBackground, const QString &videoBackground,
|
||||
const QString &horizontalTextAlignment, const QString &verticalTextAlignment,
|
||||
const QString &font, const int &fontSize, const int &imageCount,
|
||||
const int &pdfIndex, const bool &isPlaying, const QString &type,
|
||||
QObject * parent = nullptr);
|
||||
|
||||
QString text() const;
|
||||
QString type() const;
|
||||
QVariantMap serviceItem() const;
|
||||
QString audio() const;
|
||||
QString imageBackground() const;
|
||||
QString videoBackground() const;
|
||||
QString horizontalTextAlignment() const;
|
||||
QString verticalTextAlignment() const;
|
||||
QString font() const;
|
||||
int fontSize() const;
|
||||
int imageCount() const;
|
||||
int pdfIndex() const;
|
||||
bool isPlaying() const;
|
||||
|
||||
Q_INVOKABLE void setText(QString text);
|
||||
Q_INVOKABLE void setType(QString type);
|
||||
Q_INVOKABLE void setServiceItem(QVariantMap serviceItem);
|
||||
Q_INVOKABLE void setAudio(QString audio);
|
||||
Q_INVOKABLE void setImageBackground(QString imageBackground);
|
||||
Q_INVOKABLE void setVideoBackground(QString videoBackground);
|
||||
Q_INVOKABLE void setHorizontalTextAlignment(QString horizontalTextAlignment);
|
||||
Q_INVOKABLE void setVerticalTextAlignment(QString verticalTextAlignment);
|
||||
Q_INVOKABLE void setFont(QString font);
|
||||
Q_INVOKABLE void setFontSize(int fontSize);
|
||||
Q_INVOKABLE void setImageCount(int imageCount);
|
||||
Q_INVOKABLE void setPdfIndex(int pdfIndex);
|
||||
|
||||
Q_INVOKABLE void changeSlide(QVariantMap item);
|
||||
Q_INVOKABLE void play();
|
||||
Q_INVOKABLE void pause();
|
||||
Q_INVOKABLE void playPause();
|
||||
Q_INVOKABLE bool next(QVariantMap nextItem);
|
||||
Q_INVOKABLE bool previous(QVariantMap prevItem);
|
||||
|
||||
signals:
|
||||
Q_INVOKABLE void textChanged(QString text);
|
||||
Q_INVOKABLE void typeChanged(QString type);
|
||||
Q_INVOKABLE void serviceItemChanged(QVariantMap serviceItem);
|
||||
Q_INVOKABLE void audioChanged(QString audio);
|
||||
Q_INVOKABLE void imageBackgroundChanged(QString imageBackground);
|
||||
Q_INVOKABLE void videoBackgroundChanged(QString videoBackground);
|
||||
Q_INVOKABLE void horizontalTextAlignmentChanged(QString horizontalTextAlignment);
|
||||
Q_INVOKABLE void verticalTextAlignmentChanged(QString verticalTextAlignment);
|
||||
Q_INVOKABLE void fontChanged(QString font);
|
||||
Q_INVOKABLE void fontSizeChanged(int fontSize);
|
||||
Q_INVOKABLE void imageCountChanged(int imageCount);
|
||||
Q_INVOKABLE void pdfIndexChanged(int pdfIndex);
|
||||
Q_INVOKABLE void isPlayingChanged(bool isPlaying);
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
QString m_text;
|
||||
QString m_type;
|
||||
QVariantMap m_serviceItem;
|
||||
QString m_audio;
|
||||
QString m_imageBackground;
|
||||
QString m_videoBackground;
|
||||
QString m_horizontalTextAlignment;
|
||||
QString m_verticalTextAlignment;
|
||||
QString m_font;
|
||||
int m_fontSize;
|
||||
int m_imageCount;
|
||||
int m_pdfIndex;
|
||||
bool m_isPlaying;
|
||||
|
||||
int m_slideIndex;
|
||||
int m_slideSize;
|
||||
};
|
||||
|
||||
#endif //SLIDE_H
|
711
src/cpp/songsqlmodel.cpp
Normal file
711
src/cpp/songsqlmodel.cpp
Normal file
|
@ -0,0 +1,711 @@
|
|||
#include "songsqlmodel.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QSqlError>
|
||||
#include <QSqlRecord>
|
||||
#include <QSqlQuery>
|
||||
#include <QSql>
|
||||
#include <QSqlDatabase>
|
||||
#include <qabstractitemmodel.h>
|
||||
#include <qdebug.h>
|
||||
#include <qglobal.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qregexp.h>
|
||||
#include <qsqlquery.h>
|
||||
#include <qsqlrecord.h>
|
||||
|
||||
static const char *songsTableName = "songs";
|
||||
|
||||
static void createTable()
|
||||
{
|
||||
if(QSqlDatabase::database().tables().contains(songsTableName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QSqlQuery query;
|
||||
if (!query.exec("CREATE TABLE IF NOT EXISTS 'songs' ("
|
||||
" 'id' INTEGER NOT NULL,"
|
||||
" 'title' TEXT NOT NULL,"
|
||||
" 'lyrics' TEXT,"
|
||||
" 'author' TEXT,"
|
||||
" 'ccli' TEXT,"
|
||||
" 'audio' TEXT,"
|
||||
" 'vorder' TEXT,"
|
||||
" 'background' TEXT,"
|
||||
" 'backgroundType' TEXT,"
|
||||
" 'horizontalTextAlignment' TEXT,"
|
||||
" 'verticalTextAlignment' TEXT,"
|
||||
" 'font' TEXT,"
|
||||
" 'fontSize' INTEGER,"
|
||||
" PRIMARY KEY(id))")) {
|
||||
qFatal("Failed to query database: %s",
|
||||
qPrintable(query.lastError().text()));
|
||||
}
|
||||
// qDebug() << query.lastQuery();
|
||||
// qDebug() << "inserting into songs";
|
||||
|
||||
query.exec(
|
||||
"INSERT INTO songs (title, lyrics, author, ccli, audio, vorder, "
|
||||
"background, backgroundType, horizontalTextAlignment, verticalTextAlignment, font, fontSize) VALUES ('10,000 Reasons', '10,000 reasons "
|
||||
"for my heart to sing', 'Matt Redman', '13470183', '', '', '', '', 'center', 'center', '', '')");
|
||||
// qDebug() << query.lastQuery();
|
||||
query.exec("INSERT INTO songs (title, lyrics, author, ccli, audio, vorder, "
|
||||
"background, backgroundType, horizontalTextAlignment, verticalTextAlignment, font, fontSize) VALUES ('River', 'Im going down to "
|
||||
"the river', 'Jordan Feliz', '13470183', '', '', '', '', 'center', 'center', '', '')");
|
||||
query.exec(
|
||||
"INSERT INTO songs (title, lyrics, author, ccli, audio, vorder, "
|
||||
"background, backgroundType, horizontalTextAlignment, verticalTextAlignment, font, fontSize) VALUES ('Marvelous Light', 'Into marvelous "
|
||||
"light Im running', 'Chris Tomlin', '13470183', '', '', '', '', 'center', 'center', '', '')");
|
||||
|
||||
// qDebug() << query.lastQuery();
|
||||
query.exec("select * from songs");
|
||||
// qDebug() << query.lastQuery();
|
||||
}
|
||||
|
||||
SongSqlModel::SongSqlModel(QObject *parent)
|
||||
: QSqlTableModel(parent)
|
||||
{
|
||||
// qDebug() << "creating table";
|
||||
createTable();
|
||||
setTable(songsTableName);
|
||||
setEditStrategy(QSqlTableModel::OnManualSubmit);
|
||||
// make sure to call select else the model won't fill
|
||||
select();
|
||||
}
|
||||
|
||||
QVariant SongSqlModel::data(const QModelIndex &index, int role) const {
|
||||
if (role < Qt::UserRole) {
|
||||
// qDebug() << role;
|
||||
return QSqlTableModel::data(index, role);
|
||||
}
|
||||
|
||||
// qDebug() << role;
|
||||
const QSqlRecord sqlRecord = record(index.row());
|
||||
return sqlRecord.value(role - Qt::UserRole);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> SongSqlModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> names;
|
||||
names[Qt::UserRole] = "id";
|
||||
names[Qt::UserRole + 1] = "title";
|
||||
names[Qt::UserRole + 2] = "lyrics";
|
||||
names[Qt::UserRole + 3] = "author";
|
||||
names[Qt::UserRole + 4] = "ccli";
|
||||
names[Qt::UserRole + 5] = "audio";
|
||||
names[Qt::UserRole + 6] = "vorder";
|
||||
names[Qt::UserRole + 7] = "background";
|
||||
names[Qt::UserRole + 8] = "backgroundType";
|
||||
names[Qt::UserRole + 9] = "horizontalTextAlignment";
|
||||
names[Qt::UserRole + 10] = "verticalTextAlignment";
|
||||
names[Qt::UserRole + 11] = "font";
|
||||
names[Qt::UserRole + 12] = "fontSize";
|
||||
return names;
|
||||
}
|
||||
|
||||
void SongSqlModel::newSong() {
|
||||
qDebug() << "starting to add new song";
|
||||
int rows = rowCount();
|
||||
|
||||
qDebug() << rows;
|
||||
QSqlRecord recorddata = record();
|
||||
recorddata.setValue("title", "new song");
|
||||
qDebug() << recorddata;
|
||||
|
||||
if (insertRecord(rows, recorddata)) {
|
||||
submitAll();
|
||||
} else {
|
||||
qDebug() << lastError();
|
||||
};
|
||||
}
|
||||
|
||||
void SongSqlModel::deleteSong(const int &row) {
|
||||
QSqlRecord recordData = record(row);
|
||||
if (recordData.isEmpty())
|
||||
return;
|
||||
|
||||
removeRow(row);
|
||||
submitAll();
|
||||
}
|
||||
|
||||
QVariantMap SongSqlModel::getSong(const int &row) {
|
||||
// this whole function returns all data in the song
|
||||
// regardless of it's length. When new things are added
|
||||
// it will still work without refactoring.
|
||||
const QModelIndex &parent = QModelIndex();
|
||||
QVariantMap data;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
const QModelIndex idx = this->index(id, 0, parent);
|
||||
qDebug() << "%%%%%%%%%";
|
||||
qDebug() << row;
|
||||
qDebug() << idx;
|
||||
qDebug() << "%%%%%%%%%";
|
||||
if( !idx.isValid() )
|
||||
return data;
|
||||
const QHash<int,QByteArray> rn = roleNames();
|
||||
// qDebug() << rn;
|
||||
QHashIterator<int,QByteArray> it(rn);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
qDebug() << it.key() << ":" << it.value();
|
||||
data[it.value()] = idx.data(it.key());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
QStringList SongSqlModel::getLyricList(const int &row) {
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
qDebug() << row;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
qDebug() << "@@@@@@@@@@@@@@";
|
||||
qDebug() << id;
|
||||
qDebug() << "@@@@@@@@@@@@@@";
|
||||
QSqlRecord recordData = record(id);
|
||||
if (recordData.isEmpty()) {
|
||||
qDebug() << "this is not a song";
|
||||
QStringList empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
QStringList rawLyrics = recordData.value("lyrics").toString().split("\n");
|
||||
qDebug() << "HERE ARE RAW LYRICS: " << rawLyrics;
|
||||
QStringList lyrics;
|
||||
|
||||
QStringList vorder = recordData.value("vorder").toString().split(" ");
|
||||
qDebug() << vorder;
|
||||
|
||||
QStringList keywords = {"Verse 1", "Verse 2", "Verse 3", "Verse 4",
|
||||
"Verse 5", "Verse 6", "Verse 7", "Verse 8",
|
||||
"Chorus 1", "Chorus 2", "Chorus 3", "Chorus 4",
|
||||
"Bridge 1", "Bridge 2", "Bridge 3", "Bridge 4",
|
||||
"Intro 1", "Intro 2", "Ending 1", "Ending 2",
|
||||
"Other 1", "Other 2", "Other 3", "Other 4"};
|
||||
|
||||
bool firstItem = true;
|
||||
QString verse;
|
||||
QString vtitle;
|
||||
QString line;
|
||||
QMultiMap<QString, QString> verses;
|
||||
|
||||
//TODO make sure to split empty line in verse into two slides
|
||||
|
||||
// This first function pulls out each verse into our verses map
|
||||
// foreach (line, rawLyrics) {
|
||||
for (int i = 0; i < rawLyrics.length(); ++i) {
|
||||
qDebug() << "##########################";
|
||||
qDebug() << rawLyrics[i];
|
||||
qDebug() << rawLyrics.length();
|
||||
qDebug() << i;
|
||||
qDebug() << "##########################";
|
||||
if (firstItem) {
|
||||
if (keywords.contains(rawLyrics[i])) {
|
||||
qDebug() << "!!!!THIS IS FIRST LINE!!!!!";
|
||||
// qDebug() << rawLyrics[i];
|
||||
firstItem = false;
|
||||
vtitle = rawLyrics[i];
|
||||
continue;
|
||||
}
|
||||
} else if (keywords.contains(rawLyrics[i])) {
|
||||
qDebug() << "!!!!THIS IS A VTITLE!!!!!";
|
||||
// qDebug() << verse;
|
||||
// qDebug() << rawLyrics[i];
|
||||
if (verse.contains("\n\n")) {
|
||||
verse = verse.trimmed();
|
||||
qDebug() << "THIS IS A EMPTY SLIDE!" << verse;
|
||||
QStringList multiverses = verse.split("\n\n");
|
||||
foreach (verse, multiverses) {
|
||||
verses.insert(vtitle, verse);
|
||||
// qDebug() << verse;
|
||||
}
|
||||
verse.clear();
|
||||
multiverses.clear();
|
||||
vtitle = rawLyrics[i];
|
||||
continue;
|
||||
}
|
||||
verses.insert(vtitle, verse);
|
||||
verse.clear();
|
||||
vtitle = rawLyrics[i];
|
||||
continue;
|
||||
} else if (i + 1 == rawLyrics.length()) {
|
||||
qDebug() << "!!!!LAST LINE!!!!!";
|
||||
|
||||
verse.append(rawLyrics[i].trimmed() + "\n");
|
||||
if (verse.contains("\n\n")) {
|
||||
verse = verse.trimmed();
|
||||
qDebug() << "THIS IS A EMPTY SLIDE!" << verse;
|
||||
QStringList multiverses = verse.split("\n\n");
|
||||
foreach (verse, multiverses) {
|
||||
verses.insert(vtitle, verse);
|
||||
// qDebug() << verse;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
verses.insert(vtitle, verse);
|
||||
qDebug() << "&&&&&&&&&&&&";
|
||||
qDebug() << "This is final line";
|
||||
qDebug() << "and has been inserted";
|
||||
qDebug() << verses.values(vtitle);
|
||||
qDebug() << "&&&&&&&&&&&&";
|
||||
break;
|
||||
}
|
||||
qDebug() << "THIS RAWLYRICS[I]";
|
||||
qDebug() << rawLyrics[i];
|
||||
qDebug() << "THIS VTITLE";
|
||||
qDebug() << vtitle;
|
||||
verse.append(rawLyrics[i].trimmed() + "\n");
|
||||
qDebug() << verse;
|
||||
qDebug() << "APPENDED VERSE";
|
||||
}
|
||||
// qDebug() << verses;
|
||||
|
||||
// let's check to see if there is a verse order, if not return the list given
|
||||
if (vorder.first().isEmpty()) {
|
||||
qDebug() << "NO VORDER";
|
||||
foreach (verse, verses) {
|
||||
qDebug() << verse;
|
||||
lyrics.append(verse);
|
||||
}
|
||||
qDebug() << lyrics;
|
||||
return lyrics;
|
||||
}
|
||||
|
||||
// this function appends the verse that matches the verse order from the map
|
||||
// first we run through every line and check to see if the line matches
|
||||
// an item in vorder, then we append lyrics from the verse that matches
|
||||
// the verse map we created earlier. It's a multi map so we need to append
|
||||
// them in reverse as they are added in last in first out order.
|
||||
foreach (const QString &vstr, vorder) {
|
||||
foreach (line, rawLyrics) {
|
||||
if (line.startsWith(vstr.at(0)) && line.endsWith(vstr.at(1))) {
|
||||
qDebug() << "**********************";
|
||||
qDebug() << vstr;
|
||||
qDebug() << line;
|
||||
qDebug() << "**********************";
|
||||
QList<QString> values = verses.values(line);
|
||||
for (int i = values.size(); i > 0;)
|
||||
lyrics.append(values.at(--i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// qDebug() << lyrics;
|
||||
|
||||
return lyrics;
|
||||
}
|
||||
|
||||
int SongSqlModel::id() const {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString SongSqlModel::title() const {
|
||||
return m_title;
|
||||
}
|
||||
|
||||
void SongSqlModel::setTitle(const QString &title) {
|
||||
if (title == m_title)
|
||||
return;
|
||||
|
||||
m_title = title;
|
||||
|
||||
select();
|
||||
emit titleChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateTitle(const int &row, const QString &title) {
|
||||
qDebug() << "Row is " << row;
|
||||
// QSqlQuery query("select id from songs");
|
||||
// QList<int> ids;
|
||||
// while (query.next()) {
|
||||
// ids.append(query.value(0).toInt());
|
||||
// // qDebug() << ids;
|
||||
// }
|
||||
// int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("title", title);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit titleChanged();
|
||||
}
|
||||
|
||||
QString SongSqlModel::author() const {
|
||||
return m_author;
|
||||
}
|
||||
|
||||
void SongSqlModel::setAuthor(const QString &author) {
|
||||
if (author == m_author)
|
||||
return;
|
||||
|
||||
m_author = author;
|
||||
|
||||
select();
|
||||
emit authorChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateAuthor(const int &row, const QString &author) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
rowdata.setValue("author", author);
|
||||
setRecord(id, rowdata);
|
||||
submitAll();
|
||||
emit authorChanged();
|
||||
}
|
||||
|
||||
QString SongSqlModel::lyrics() const {
|
||||
return m_lyrics;
|
||||
}
|
||||
|
||||
void SongSqlModel::setLyrics(const QString &lyrics) {
|
||||
if (lyrics == m_lyrics)
|
||||
return;
|
||||
|
||||
m_lyrics = lyrics;
|
||||
|
||||
select();
|
||||
emit lyricsChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateLyrics(const int &row, const QString &lyrics) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << lyrics;
|
||||
rowdata.setValue("lyrics", lyrics);
|
||||
qDebug() << rowdata.value("lyrics");
|
||||
setRecord(id, rowdata);
|
||||
submitAll();
|
||||
emit lyricsChanged();
|
||||
}
|
||||
|
||||
QString SongSqlModel::ccli() const {
|
||||
return m_ccli;
|
||||
}
|
||||
|
||||
void SongSqlModel::setCcli(const QString &ccli) {
|
||||
if (ccli == m_ccli)
|
||||
return;
|
||||
|
||||
m_ccli = ccli;
|
||||
|
||||
select();
|
||||
emit ccliChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateCcli(const int &row, const QString &ccli) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
rowdata.setValue("ccli", ccli);
|
||||
setRecord(id, rowdata);
|
||||
submitAll();
|
||||
emit ccliChanged();
|
||||
}
|
||||
|
||||
QString SongSqlModel::audio() const {
|
||||
return m_audio;
|
||||
}
|
||||
|
||||
void SongSqlModel::setAudio(const QString &audio) {
|
||||
if (audio == m_audio)
|
||||
return;
|
||||
|
||||
m_audio = audio;
|
||||
|
||||
select();
|
||||
emit audioChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateAudio(const int &row, const QString &audio) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
rowdata.setValue("audio", audio);
|
||||
setRecord(id, rowdata);
|
||||
submitAll();
|
||||
emit audioChanged();
|
||||
}
|
||||
|
||||
QString SongSqlModel::vorder() const { return m_vorder; }
|
||||
|
||||
void SongSqlModel::setVerseOrder(const QString &vorder) {
|
||||
if (vorder == m_vorder)
|
||||
return;
|
||||
|
||||
m_vorder = vorder;
|
||||
|
||||
select();
|
||||
emit vorderChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateVerseOrder(const int &row, const QString &vorder) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
rowdata.setValue("vorder", vorder);
|
||||
setRecord(id, rowdata);
|
||||
submitAll();
|
||||
emit vorderChanged();
|
||||
}
|
||||
|
||||
QString SongSqlModel::background() const { return m_background; }
|
||||
|
||||
void SongSqlModel::setBackground(const QString &background) {
|
||||
if (background == m_background)
|
||||
return;
|
||||
|
||||
m_background = background;
|
||||
|
||||
select();
|
||||
emit backgroundChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateBackground(const int &row, const QString &background) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
rowdata.setValue("background", background);
|
||||
setRecord(id, rowdata);
|
||||
submitAll();
|
||||
emit backgroundChanged();
|
||||
}
|
||||
|
||||
QString SongSqlModel::backgroundType() const { return m_backgroundType; }
|
||||
|
||||
void SongSqlModel::setBackgroundType(const QString &backgroundType) {
|
||||
if (backgroundType == m_backgroundType)
|
||||
return;
|
||||
|
||||
m_backgroundType = backgroundType;
|
||||
|
||||
select();
|
||||
emit backgroundTypeChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateBackgroundType(const int &row, const QString &backgroundType) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
rowdata.setValue("backgroundType", backgroundType);
|
||||
setRecord(id, rowdata);
|
||||
submitAll();
|
||||
emit backgroundTypeChanged();
|
||||
}
|
||||
|
||||
QString SongSqlModel::horizontalTextAlignment() const {
|
||||
return m_horizontalTextAlignment;
|
||||
}
|
||||
|
||||
void SongSqlModel::setHorizontalTextAlignment(const QString &horizontalTextAlignment) {
|
||||
if (horizontalTextAlignment == m_horizontalTextAlignment)
|
||||
return;
|
||||
|
||||
m_horizontalTextAlignment = horizontalTextAlignment;
|
||||
|
||||
select();
|
||||
emit horizontalTextAlignmentChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateHorizontalTextAlignment(const int &row, const QString &horizontalTextAlignment) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("horizontalTextAlignment", horizontalTextAlignment);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit horizontalTextAlignmentChanged();
|
||||
}
|
||||
|
||||
QString SongSqlModel::verticalTextAlignment() const {
|
||||
return m_verticalTextAlignment;
|
||||
}
|
||||
|
||||
void SongSqlModel::setVerticalTextAlignment(const QString &verticalTextAlignment) {
|
||||
if (verticalTextAlignment == m_verticalTextAlignment)
|
||||
return;
|
||||
|
||||
m_verticalTextAlignment = verticalTextAlignment;
|
||||
|
||||
select();
|
||||
emit verticalTextAlignmentChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateVerticalTextAlignment(const int &row, const QString &verticalTextAlignment) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("verticalTextAlignment", verticalTextAlignment);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit verticalTextAlignmentChanged();
|
||||
}
|
||||
|
||||
QString SongSqlModel::font() const {
|
||||
return m_font;
|
||||
}
|
||||
|
||||
void SongSqlModel::setFont(const QString &font) {
|
||||
if (font == m_font)
|
||||
return;
|
||||
|
||||
m_font = font;
|
||||
|
||||
select();
|
||||
emit fontChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateFont(const int &row, const QString &font) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("font", font);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit fontChanged();
|
||||
}
|
||||
|
||||
int SongSqlModel::fontSize() const {
|
||||
return m_fontSize;
|
||||
}
|
||||
|
||||
void SongSqlModel::setFontSize(const int &fontSize) {
|
||||
if (fontSize == m_fontSize)
|
||||
return;
|
||||
|
||||
m_fontSize = fontSize;
|
||||
|
||||
select();
|
||||
emit fontSizeChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the lyrics from outside the delegate
|
||||
void SongSqlModel::updateFontSize(const int &row, const int &fontSize) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from songs");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("fontSize", fontSize);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit fontSizeChanged();
|
||||
}
|
110
src/cpp/songsqlmodel.h
Normal file
110
src/cpp/songsqlmodel.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
#ifndef SONGSQLMODEL_H
|
||||
#define SONGSQLMODEL_H
|
||||
|
||||
#include <QSqlTableModel>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qqml.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
class SongSqlModel : public QSqlTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int id READ id)
|
||||
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
|
||||
Q_PROPERTY(QString lyrics READ lyrics WRITE setLyrics NOTIFY lyricsChanged)
|
||||
Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
|
||||
Q_PROPERTY(QString ccli READ ccli WRITE setCcli NOTIFY ccliChanged)
|
||||
Q_PROPERTY(QString audio READ audio WRITE setAudio NOTIFY audioChanged)
|
||||
Q_PROPERTY(QString vorder READ vorder WRITE setVerseOrder NOTIFY vorderChanged)
|
||||
Q_PROPERTY(QString background READ background WRITE setBackground NOTIFY backgroundChanged)
|
||||
Q_PROPERTY(QString backgroundType READ backgroundType WRITE setBackgroundType NOTIFY backgroundTypeChanged)
|
||||
Q_PROPERTY(QString horizontalTextAlignment READ horizontalTextAlignment WRITE setHorizontalTextAlignment NOTIFY horizontalTextAlignmentChanged)
|
||||
Q_PROPERTY(QString verticalTextAlignment READ verticalTextAlignment WRITE setVerticalTextAlignment NOTIFY verticalTextAlignmentChanged)
|
||||
Q_PROPERTY(QString font READ font WRITE setFont NOTIFY fontChanged)
|
||||
Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
|
||||
QML_ELEMENT
|
||||
|
||||
public:
|
||||
SongSqlModel(QObject *parent = 0);
|
||||
|
||||
int id() const;
|
||||
QString title() const;
|
||||
QString lyrics() const;
|
||||
QString author() const;
|
||||
QString ccli() const;
|
||||
QString audio() const;
|
||||
QString vorder() const;
|
||||
QString background() const;
|
||||
QString backgroundType() const;
|
||||
QString horizontalTextAlignment() const;
|
||||
QString verticalTextAlignment() const;
|
||||
QString font() const;
|
||||
int fontSize() const;
|
||||
|
||||
void setTitle(const QString &title);
|
||||
void setLyrics(const QString &lyrics);
|
||||
void setAuthor(const QString &author);
|
||||
void setCcli(const QString &ccli);
|
||||
void setAudio(const QString &audio);
|
||||
void setVerseOrder(const QString &vorder);
|
||||
void setBackground(const QString &background);
|
||||
void setBackgroundType(const QString &backgroundType);
|
||||
void setHorizontalTextAlignment(const QString &horizontalTextAlignment);
|
||||
void setVerticalTextAlignment(const QString &verticalTextAlignment);
|
||||
void setFont(const QString &font);
|
||||
void setFontSize(const int &fontSize);
|
||||
|
||||
Q_INVOKABLE void updateTitle(const int &row, const QString &title);
|
||||
Q_INVOKABLE void updateLyrics(const int &row, const QString &lyrics);
|
||||
Q_INVOKABLE void updateAuthor(const int &row, const QString &author);
|
||||
Q_INVOKABLE void updateCcli(const int &row, const QString &ccli);
|
||||
Q_INVOKABLE void updateAudio(const int &row, const QString &audio);
|
||||
Q_INVOKABLE void updateVerseOrder(const int &row, const QString &vorder);
|
||||
Q_INVOKABLE void updateBackground(const int &row, const QString &background);
|
||||
Q_INVOKABLE void updateBackgroundType(const int &row, const QString &backgroundType);
|
||||
Q_INVOKABLE void updateHorizontalTextAlignment(const int &row,
|
||||
const QString &horizontalTextAlignment);
|
||||
Q_INVOKABLE void updateVerticalTextAlignment(const int &row,
|
||||
const QString &horizontalTextAlignment);
|
||||
Q_INVOKABLE void updateFont(const int &row, const QString &font);
|
||||
Q_INVOKABLE void updateFontSize(const int &row, const int &fontSize);
|
||||
|
||||
Q_INVOKABLE void newSong();
|
||||
Q_INVOKABLE void deleteSong(const int &row);
|
||||
Q_INVOKABLE QVariantMap getSong(const int &row);
|
||||
Q_INVOKABLE QStringList getLyricList(const int &row);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
signals:
|
||||
void titleChanged();
|
||||
void lyricsChanged();
|
||||
void authorChanged();
|
||||
void ccliChanged();
|
||||
void audioChanged();
|
||||
void vorderChanged();
|
||||
void backgroundChanged();
|
||||
void backgroundTypeChanged();
|
||||
void horizontalTextAlignmentChanged();
|
||||
void verticalTextAlignmentChanged();
|
||||
void fontChanged();
|
||||
void fontSizeChanged();
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
QString m_title;
|
||||
QString m_lyrics;
|
||||
QString m_author;
|
||||
QString m_ccli;
|
||||
QString m_audio;
|
||||
QString m_vorder;
|
||||
QString m_background;
|
||||
QString m_backgroundType;
|
||||
QString m_horizontalTextAlignment;
|
||||
QString m_verticalTextAlignment;
|
||||
QString m_font;
|
||||
int m_fontSize;
|
||||
};
|
||||
|
||||
#endif //SONGSQLMODEL_H
|
159
src/cpp/thumbnail.cpp
Normal file
159
src/cpp/thumbnail.cpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
#include "thumbnail.h"
|
||||
#include <QDebug>
|
||||
|
||||
Thumbnail::Thumbnail(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Thumbnail::Thumbnail(const QString &owner, const QString &type, QObject *parent)
|
||||
: QObject(parent),m_owner(owner),m_type(type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Thumbnail::Thumbnail(const QString &owner, const QString &type, const QString &background,
|
||||
const QString &backgroundType, QObject *parent)
|
||||
: QObject(parent),m_owner(owner),m_type(type),m_background(background),
|
||||
m_backgroundType(backgroundType)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Thumbnail::Thumbnail(const QString &owner, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
QObject *parent)
|
||||
: QObject(parent),m_owner(owner),m_type(type),m_background(background),
|
||||
m_backgroundType(backgroundType),m_text(text)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Thumbnail::Thumbnail(const QString &owner, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
const QString &songVerse, QObject *parent)
|
||||
: QObject(parent),m_owner(owner),m_type(type),m_background(background),
|
||||
m_backgroundType(backgroundType),m_text(text),m_songVerse(songVerse)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Thumbnail::Thumbnail(const QString &owner, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
const QString &font, const int &fontSize, const QString &songVerse
|
||||
QObject *parent)
|
||||
: QObject(parent),m_owner(owner),m_type(type),m_background(background),
|
||||
m_backgroundType(backgroundType),m_text(text),m_font(font),m_fontSize(fontSize),
|
||||
m_songVerse(songVerse)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString Thumbnail::owner() const {
|
||||
return m_owner;
|
||||
}
|
||||
|
||||
QString Thumbnail::type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
QString Thumbnail::songVerse() const {
|
||||
return m_songVerse;
|
||||
}
|
||||
|
||||
QString Thumbnail::background() const
|
||||
{
|
||||
return m_background;
|
||||
}
|
||||
|
||||
QString Thumbnail::backgroundType() const
|
||||
{
|
||||
return m_backgroundType;
|
||||
}
|
||||
|
||||
QStringList Thumbnail::text() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
QString Thumbnail::font() const {
|
||||
return m_font;
|
||||
}
|
||||
|
||||
int Thumbnail::fontSize() const {
|
||||
return m_fontSize;
|
||||
}
|
||||
|
||||
void Thumbnail::setOwner(QString owner)
|
||||
{
|
||||
if (m_owner == owner)
|
||||
return;
|
||||
|
||||
m_owner = owner;
|
||||
emit ownerChanged(m_owner);
|
||||
}
|
||||
|
||||
void Thumbnail::setType(QString type)
|
||||
{
|
||||
if (m_type == type)
|
||||
return;
|
||||
|
||||
m_type = type;
|
||||
emit typeChanged(m_type);
|
||||
}
|
||||
|
||||
void Thumbnail::setSongVerse(QString songVerse)
|
||||
{
|
||||
if (m_songVerse == songVerse)
|
||||
return;
|
||||
|
||||
m_songVerse = songVerse;
|
||||
emit songVerseChanged(m_songVerse);
|
||||
}
|
||||
|
||||
void Thumbnail::setBackground(QString background)
|
||||
{
|
||||
if (m_background == background)
|
||||
return;
|
||||
|
||||
m_background = background;
|
||||
emit backgroundChanged(m_background);
|
||||
}
|
||||
|
||||
void Thumbnail::setBackgroundType(QString backgroundType)
|
||||
{
|
||||
if (m_backgroundType == backgroundType)
|
||||
return;
|
||||
|
||||
m_backgroundType = backgroundType;
|
||||
emit backgroundTypeChanged(m_backgroundType);
|
||||
}
|
||||
|
||||
void Thumbnail::setText(QStringList text)
|
||||
{
|
||||
if (m_text == text)
|
||||
return;
|
||||
|
||||
m_text = text;
|
||||
emit textChanged(m_text);
|
||||
|
||||
}
|
||||
|
||||
void Thumbnail::setFont(QString font)
|
||||
{
|
||||
if (m_font == font)
|
||||
return;
|
||||
|
||||
m_font = font;
|
||||
emit fontChanged(m_font);
|
||||
}
|
||||
|
||||
void Thumbnail::setFontSize(int fontSize)
|
||||
{
|
||||
if (m_fontSize == fontSize)
|
||||
return;
|
||||
|
||||
m_fontSize = fontSize;
|
||||
emit fontSizeChanged(m_fontSize);
|
||||
}
|
74
src/cpp/thumbnail.h
Normal file
74
src/cpp/thumbnail.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
#ifndef THUMBNAIL_H
|
||||
#define THUMBNAIL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <qobject.h>
|
||||
|
||||
class Thumbnail : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString owner READ owner WRITE setOwner NOTIFY ownerChanged)
|
||||
Q_PROPERTY(QString type READ type WRITE setType NOTIFY typeChanged)
|
||||
Q_PROPERTY(QString songVerse READ songVerse WRITE setSongVerse NOTIFY songVerseChanged)
|
||||
Q_PROPERTY(QString background READ background WRITE setBackground NOTIFY backgroundChanged)
|
||||
Q_PROPERTY(QString backgroundType READ backgroundType WRITE setBackgroundType NOTIFY backgroundTypeChanged)
|
||||
Q_PROPERTY(QStringList text READ text WRITE setText NOTIFY textChanged)
|
||||
Q_PROPERTY(QString font READ font WRITE setFont NOTIFY fontChanged)
|
||||
Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
|
||||
|
||||
public:
|
||||
explicit Thumbnail(QObject *parent = nullptr);
|
||||
Thumbnail(const QString &owner, const QString &type, QObject * parent = nullptr);
|
||||
Thumbnail(const QString &owner, const QString &type, const QString &background,
|
||||
const QString &backgroundType, QObject * parent = nullptr);
|
||||
Thumbnail(const QString &owner, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
QObject * parent = nullptr);
|
||||
Thumbnail(const QString &owner, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
const QString &songVerse, QObject * parent = nullptr);
|
||||
Thumbnail(const QString &owner, const QString &type, const QString &background,
|
||||
const QString &backgroundType, const QStringList &text,
|
||||
const QString &songVerse, const QString &font,
|
||||
const int &fontSize, QObject * parent = nullptr);
|
||||
|
||||
QString owner() const;
|
||||
QString type() const;
|
||||
QString songVerse() const;
|
||||
QString background() const;
|
||||
QString backgroundType() const;
|
||||
QStringList text() const;
|
||||
QString font() const;
|
||||
int fontSize() const;
|
||||
|
||||
void setOwner(QString owner);
|
||||
void setType(QString type);
|
||||
void setSongVerse(QString songVerse);
|
||||
void setBackground(QString background);
|
||||
void setBackgroundType(QString backgroundType);
|
||||
void setText(QStringList text);
|
||||
void setFont(QString font);
|
||||
void setFontSize(int fontSize);
|
||||
|
||||
signals:
|
||||
void ownerChanged(QString owner);
|
||||
void typeChanged(QString type);
|
||||
void songVerseChanged(QString songVerse);
|
||||
void backgroundChanged(QString background);
|
||||
void backgroundTypeChanged(QString backgroundType);
|
||||
void textChanged(QStringList text);
|
||||
void fontChanged(QString font);
|
||||
void fontSizeChanged(int fontSize);
|
||||
|
||||
private:
|
||||
QString m_owner;
|
||||
QString m_type;
|
||||
QString m_songVerse;
|
||||
QString m_background;
|
||||
QString m_backgroundType;
|
||||
QStringList m_text;
|
||||
QString m_font;
|
||||
int m_fontSize;
|
||||
};
|
||||
|
||||
#endif // THUMBNAIL_H
|
316
src/cpp/videosqlmodel.cpp
Normal file
316
src/cpp/videosqlmodel.cpp
Normal file
|
@ -0,0 +1,316 @@
|
|||
#include "videosqlmodel.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QSqlError>
|
||||
#include <QSqlRecord>
|
||||
#include <QSqlQuery>
|
||||
#include <QSql>
|
||||
#include <QSqlDatabase>
|
||||
#include <QFileInfo>
|
||||
#include <qabstractitemmodel.h>
|
||||
#include <qdebug.h>
|
||||
#include <qnamespace.h>
|
||||
#include <qobject.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qsqlrecord.h>
|
||||
#include <qurl.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
static const char *videosTableName = "videos";
|
||||
|
||||
static void createVideoTable()
|
||||
{
|
||||
if(QSqlDatabase::database().tables().contains(videosTableName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QSqlQuery query;
|
||||
if (!query.exec("CREATE TABLE IF NOT EXISTS 'videos' ("
|
||||
" 'id' INTEGER NOT NULL,"
|
||||
" 'title' TEXT NOT NULL,"
|
||||
" 'filePath' TEXT NOT NULL,"
|
||||
" 'startTime' REAL,"
|
||||
" 'endTime' REAL,"
|
||||
" 'loop' BOOLEAN NOT NULL DEFAULT 0,"
|
||||
" PRIMARY KEY(id))")) {
|
||||
qFatal("Failed to query database: %s",
|
||||
qPrintable(query.lastError().text()));
|
||||
}
|
||||
qDebug() << query.lastQuery();
|
||||
qDebug() << "inserting into videos";
|
||||
|
||||
query.exec("INSERT INTO videos (title, filePath) VALUES ('The Test', '/home/chris/nextcloud/tfc/openlp/videos/test.mp4')");
|
||||
qDebug() << query.lastQuery();
|
||||
query.exec("INSERT INTO videos (title, filePath) VALUES ('Sabbath', '/home/chris/nextcloud/tfc/openlp/videos/Sabbath.mp4')");
|
||||
|
||||
query.exec("select * from videos");
|
||||
qDebug() << query.lastQuery();
|
||||
}
|
||||
|
||||
VideoSqlModel::VideoSqlModel(QObject *parent) : QSqlTableModel(parent) {
|
||||
qDebug() << "creating video table";
|
||||
createVideoTable();
|
||||
|
||||
QSqlQuery query("PRAGMA table_info(videos)");
|
||||
while (query.next()) {
|
||||
QString title = query.value(1).toString();
|
||||
qDebug() << title;
|
||||
}
|
||||
|
||||
setTable(videosTableName);
|
||||
setEditStrategy(QSqlTableModel::OnManualSubmit);
|
||||
// make sure to call select else the model won't fill
|
||||
select();
|
||||
}
|
||||
|
||||
QVariant VideoSqlModel::data(const QModelIndex &index, int role) const {
|
||||
if (role < Qt::UserRole) {
|
||||
return QSqlTableModel::data(index, role);
|
||||
}
|
||||
|
||||
// qDebug() << role;
|
||||
const QSqlRecord sqlRecord = record(index.row());
|
||||
return sqlRecord.value(role - Qt::UserRole);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> VideoSqlModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> names;
|
||||
names[Qt::UserRole] = "id";
|
||||
names[Qt::UserRole + 1] = "title";
|
||||
names[Qt::UserRole + 2] = "filePath";
|
||||
names[Qt::UserRole + 3] = "startTime";
|
||||
names[Qt::UserRole + 4] = "endTime";
|
||||
names[Qt::UserRole + 5] = "loop";
|
||||
return names;
|
||||
}
|
||||
|
||||
void VideoSqlModel::newVideo(const QUrl &filePath) {
|
||||
qDebug() << "adding new video";
|
||||
int rows = rowCount();
|
||||
|
||||
qDebug() << rows;
|
||||
QSqlRecord recordData = record();
|
||||
QFileInfo fileInfo = filePath.toString();
|
||||
QString title = fileInfo.baseName();
|
||||
recordData.setValue("title", title);
|
||||
recordData.setValue("filePath", filePath);
|
||||
recordData.setValue("loop", 0);
|
||||
|
||||
if (insertRecord(rows, recordData)) {
|
||||
submitAll();
|
||||
} else {
|
||||
qDebug() << lastError();
|
||||
};
|
||||
}
|
||||
|
||||
void VideoSqlModel::deleteVideo(const int &row) {
|
||||
QSqlRecord recordData = record(row);
|
||||
if (recordData.isEmpty())
|
||||
return;
|
||||
|
||||
removeRow(row);
|
||||
submitAll();
|
||||
}
|
||||
|
||||
int VideoSqlModel::id() const {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString VideoSqlModel::title() const {
|
||||
return m_title;
|
||||
}
|
||||
|
||||
void VideoSqlModel::setTitle(const QString &title) {
|
||||
if (title == m_title)
|
||||
return;
|
||||
|
||||
m_title = title;
|
||||
|
||||
select();
|
||||
emit titleChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the title from outside the delegate
|
||||
void VideoSqlModel::updateTitle(const int &row, const QString &title) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from videos");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("title", title);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit titleChanged();
|
||||
}
|
||||
|
||||
QUrl VideoSqlModel::filePath() const {
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
void VideoSqlModel::setFilePath(const QUrl &filePath) {
|
||||
if (filePath == m_filePath)
|
||||
return;
|
||||
|
||||
m_filePath = filePath;
|
||||
|
||||
select();
|
||||
emit filePathChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the filepath from outside the delegate
|
||||
void VideoSqlModel::updateFilePath(const int &row, const QUrl &filePath) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from videos");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("filePath", filePath);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit filePathChanged();
|
||||
}
|
||||
|
||||
|
||||
int VideoSqlModel::startTime() const {
|
||||
return m_startTime;
|
||||
}
|
||||
|
||||
void VideoSqlModel::setStartTime(const int &startTime) {
|
||||
if (startTime == m_startTime)
|
||||
return;
|
||||
|
||||
m_startTime = startTime;
|
||||
|
||||
select();
|
||||
emit startTimeChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the title from outside the delegate
|
||||
void VideoSqlModel::updateStartTime(const int &row, const int &startTime) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from videos");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("startTime", startTime);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit startTimeChanged();
|
||||
}
|
||||
|
||||
int VideoSqlModel::endTime() const {
|
||||
return m_endTime;
|
||||
}
|
||||
|
||||
void VideoSqlModel::setEndTime(const int &endTime) {
|
||||
if (endTime == m_endTime)
|
||||
return;
|
||||
|
||||
m_endTime = endTime;
|
||||
|
||||
select();
|
||||
emit endTimeChanged();
|
||||
}
|
||||
|
||||
// This function is for updating the title from outside the delegate
|
||||
void VideoSqlModel::updateEndTime(const int &row, const int &endTime) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from videos");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("endTime", endTime);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit endTimeChanged();
|
||||
}
|
||||
|
||||
bool VideoSqlModel::loop() const {
|
||||
return m_loop;
|
||||
}
|
||||
|
||||
void VideoSqlModel::setLoop(const bool &loop) {
|
||||
if (loop == m_loop)
|
||||
return;
|
||||
|
||||
m_loop = loop;
|
||||
|
||||
select();
|
||||
emit loopChanged();
|
||||
}
|
||||
|
||||
// This function is for updating looping from outside the delegate
|
||||
void VideoSqlModel::updateLoop(const int &row, const bool &loop) {
|
||||
qDebug() << "Row is " << row;
|
||||
QSqlQuery query("select id from videos");
|
||||
QList<int> ids;
|
||||
while (query.next()) {
|
||||
ids.append(query.value(0).toInt());
|
||||
// qDebug() << ids;
|
||||
}
|
||||
int id = ids.indexOf(row,0);
|
||||
|
||||
QSqlRecord rowdata = record(id);
|
||||
qDebug() << rowdata;
|
||||
rowdata.setValue("loop", loop);
|
||||
setRecord(id, rowdata);
|
||||
qDebug() << rowdata;
|
||||
submitAll();
|
||||
emit loopChanged();
|
||||
}
|
||||
|
||||
QVariantMap VideoSqlModel::getVideo(const int &row) {
|
||||
// qDebug() << "Row we are getting is " << row;
|
||||
// QVariantList video;
|
||||
// QSqlRecord rec = record(row);
|
||||
// qDebug() << rec.value("title");
|
||||
// video.append(rec.value("title"));
|
||||
// video.append(rec.value("filePath"));
|
||||
// return video;
|
||||
|
||||
QVariantMap data;
|
||||
const QModelIndex idx = this->index(row,0);
|
||||
// qDebug() << idx;
|
||||
if( !idx.isValid() )
|
||||
return data;
|
||||
const QHash<int,QByteArray> rn = roleNames();
|
||||
// qDebug() << rn;
|
||||
QHashIterator<int,QByteArray> it(rn);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
qDebug() << it.key() << ":" << it.value();
|
||||
data[it.value()] = idx.data(it.key());
|
||||
}
|
||||
return data;
|
||||
|
||||
}
|
67
src/cpp/videosqlmodel.h
Normal file
67
src/cpp/videosqlmodel.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
#ifndef VIDEOSQLMODEL_H
|
||||
#define VIDEOSQLMODEL_H
|
||||
|
||||
#include <QSqlTableModel>
|
||||
#include <qobject.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qqml.h>
|
||||
#include <qurl.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
class VideoSqlModel : public QSqlTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int id READ id)
|
||||
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
|
||||
Q_PROPERTY(QUrl filePath READ filePath WRITE setFilePath NOTIFY filePathChanged)
|
||||
Q_PROPERTY(int startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
|
||||
Q_PROPERTY(int endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
|
||||
Q_PROPERTY(bool loop READ loop WRITE setLoop NOTIFY loopChanged)
|
||||
QML_ELEMENT
|
||||
|
||||
public:
|
||||
VideoSqlModel(QObject *parent = 0);
|
||||
|
||||
int id() const;
|
||||
QString title() const;
|
||||
QUrl filePath() const;
|
||||
int startTime() const;
|
||||
int endTime() const;
|
||||
bool loop() const;
|
||||
|
||||
void setTitle(const QString &title);
|
||||
void setFilePath(const QUrl &filePath);
|
||||
void setStartTime(const int &startTime);
|
||||
void setEndTime(const int &endTime);
|
||||
void setLoop(const bool &loop);
|
||||
|
||||
Q_INVOKABLE void updateTitle(const int &row, const QString &title);
|
||||
Q_INVOKABLE void updateFilePath(const int &row, const QUrl &filePath);
|
||||
Q_INVOKABLE void updateStartTime(const int &row, const int &startTime);
|
||||
Q_INVOKABLE void updateEndTime(const int &row, const int &endTime);
|
||||
Q_INVOKABLE void updateLoop(const int &row, const bool &loop);
|
||||
|
||||
Q_INVOKABLE void newVideo(const QUrl &filePath);
|
||||
Q_INVOKABLE void deleteVideo(const int &row);
|
||||
Q_INVOKABLE QVariantMap getVideo(const int &row);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
signals:
|
||||
void titleChanged();
|
||||
void filePathChanged();
|
||||
void loopChanged();
|
||||
void startTimeChanged();
|
||||
void endTimeChanged();
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
QString m_title;
|
||||
QUrl m_filePath;
|
||||
int m_startTime;
|
||||
int m_endTime;
|
||||
bool m_loop;
|
||||
};
|
||||
|
||||
#endif //VIDEOSQLMODEL_H
|
Loading…
Add table
Add a link
Reference in a new issue