Add viewer of slides in current song and combobox for song selection

This commit is contained in:
A/V User 2021-07-25 01:11:40 -05:00
parent a2b8073ce8
commit f1d16ccd19
8 changed files with 254 additions and 25 deletions

View File

@ -1,6 +1,6 @@
QT += core gui QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += webenginewidgets widgets greaterThan(QT_MAJOR_VERSION, 4): QT += network widgets
CONFIG += c++17 CONFIG += c++17

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.14.0, 2021-07-18T12:05:53. --> <!-- Written by QtCreator 4.14.0, 2021-07-25T01:11:28. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>
@ -91,7 +91,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.15.2 MSVC2019 64bit</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.15.2 MSVC2019 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.15.2 MSVC2019 64bit</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.15.2 MSVC2019 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5152.win64_msvc2019_64_kit</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5152.win64_msvc2019_64_kit</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value> <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value> <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value> <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0"> <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
@ -294,12 +294,14 @@
<valuelist type="QVariantList" key="CustomOutputParsers"/> <valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value> <value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/> <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:C:/Users/avuser/Documents/SlideController/SlideController.pro</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value> <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/Users/avuser/Documents/SlideController/SlideController.pro</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value> <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value> <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value> <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value> <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">C:/Users/avuser/Documents/build-SlideController-Desktop_Qt_5_15_2_MSVC2019_64bit-Release</value>
</valuemap> </valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value> <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap> </valuemap>

View File

@ -4,8 +4,8 @@
#include <QLineEdit> #include <QLineEdit>
#include <QPushButton> #include <QPushButton>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QWebEngineView>
#include "slideview.hpp"
#include "mainwindow.hpp" #include "mainwindow.hpp"
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) { MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {
@ -14,16 +14,13 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {
setWindowTitle(tr("Slide Controller 9000")); setWindowTitle(tr("Slide Controller 9000"));
const auto mainWidget = new QWidget(this); const auto mainWidget = new QWidget(this);
const auto rootLyt = new QVBoxLayout; const auto rootLyt = new QVBoxLayout;
const auto viewsLayout = new QHBoxLayout; //const auto viewsLayout = new QHBoxLayout;
const auto controlsLayout = new QGridLayout; const auto controlsLayout = new QGridLayout;
const auto slideView = new QWebEngineView(mainWidget); const auto slideView = new SlideView(this);
setCentralWidget(mainWidget); setCentralWidget(mainWidget);
mainWidget->setLayout(rootLyt); mainWidget->setLayout(rootLyt);
viewsLayout->addWidget(slideView, 1); rootLyt->addWidget(slideView);
viewsLayout->setSizeConstraint(QLayout::SetFixedSize);
rootLyt->addLayout(viewsLayout);
rootLyt->addLayout(controlsLayout); rootLyt->addLayout(controlsLayout);
slideView->setUrl(QUrl("http://127.0.0.1:4316/main"));
// setup slide controls // setup slide controls
const auto btnPrevSong = new QPushButton(tr("Previous Song (Left)"), this); const auto btnPrevSong = new QPushButton(tr("Previous Song (Left)"), this);
const auto btnPrevSlide = new QPushButton(tr("Previous Slide (Up)"), this); const auto btnPrevSlide = new QPushButton(tr("Previous Slide (Up)"), this);
@ -32,9 +29,9 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {
const auto btnBlankSlides = new QPushButton(tr("Blank Slides (,)"), this); const auto btnBlankSlides = new QPushButton(tr("Blank Slides (,)"), this);
const auto btnShowSlides = new QPushButton(tr("Show Slides (.)"), this); const auto btnShowSlides = new QPushButton(tr("Show Slides (.)"), this);
rootLyt->addLayout(controlsLayout); rootLyt->addLayout(controlsLayout);
controlsLayout->addWidget(btnPrevSong, 0, 0); controlsLayout->addWidget(btnPrevSlide, 0, 0);
controlsLayout->addWidget(btnPrevSlide, 0, 1); controlsLayout->addWidget(btnNextSlide, 0, 1);
controlsLayout->addWidget(btnNextSlide, 1, 0); controlsLayout->addWidget(btnPrevSong, 1, 0);
controlsLayout->addWidget(btnNextSong, 1, 1); controlsLayout->addWidget(btnNextSong, 1, 1);
controlsLayout->addWidget(btnBlankSlides, 2, 0); controlsLayout->addWidget(btnBlankSlides, 2, 0);
controlsLayout->addWidget(btnShowSlides, 2, 1); controlsLayout->addWidget(btnShowSlides, 2, 1);
@ -52,6 +49,11 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {
connect(btnBlankSlides, &QPushButton::clicked, &m_openlpClient, &OpenLPClient::blankScreen); connect(btnBlankSlides, &QPushButton::clicked, &m_openlpClient, &OpenLPClient::blankScreen);
connect(btnBlankSlides, &QPushButton::clicked, &m_obsClient, &OBSClient::hideSlides); connect(btnBlankSlides, &QPushButton::clicked, &m_obsClient, &OBSClient::hideSlides);
connect(btnShowSlides, &QPushButton::clicked, &m_openlpClient, &OpenLPClient::showSlides); connect(btnShowSlides, &QPushButton::clicked, &m_openlpClient, &OpenLPClient::showSlides);
connect(&m_openlpClient, &OpenLPClient::pollUpdate, slideView, &SlideView::pollUpdate);
connect(&m_openlpClient, &OpenLPClient::songListUpdate, slideView, &SlideView::songListUpdate);
connect(&m_openlpClient, &OpenLPClient::slideListUpdate, slideView, &SlideView::slideListUpdate);
connect(slideView, &SlideView::songChanged, &m_openlpClient, &OpenLPClient::changeSong);
connect(slideView, &SlideView::slideChanged, &m_openlpClient, &OpenLPClient::changeSlide);
// setup scene selector // setup scene selector
const auto btnObsHideSlides = new QPushButton(tr("Hide Slides in OBS (;)"), mainWidget); const auto btnObsHideSlides = new QPushButton(tr("Hide Slides in OBS (;)"), mainWidget);
const auto btnObsShowSlides = new QPushButton(tr("Show Slides in OBS (')"), mainWidget); const auto btnObsShowSlides = new QPushButton(tr("Show Slides in OBS (')"), mainWidget);

View File

@ -25,7 +25,5 @@ class OBSClient : public QObject
private: private:
void get(QString url); void get(QString url);
signals:
}; };

View File

@ -1,9 +1,19 @@
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonValueRef>
#include <QNetworkReply>
#include "openlpclient.hpp" #include "openlpclient.hpp"
OpenLPClient::OpenLPClient(QObject *parent): QObject(parent) { OpenLPClient::OpenLPClient(QObject *parent): QObject(parent) {
poll();
m_pollTimer.start(500);
connect(&m_pollTimer, &QTimer::timeout, this, &OpenLPClient::poll);
connect(m_nam, &QNetworkAccessManager::finished, this, &OpenLPClient::handleGeneralResponse);
connect(m_songListNam, &QNetworkAccessManager::finished, this, &OpenLPClient::handleSongListResponse);
connect(m_slideListNam, &QNetworkAccessManager::finished, this, &OpenLPClient::handleSlideListResponse);
connect(m_pollingNam, &QNetworkAccessManager::finished, this, &OpenLPClient::handlePollResponse);
} }
void OpenLPClient::nextSlide() { void OpenLPClient::nextSlide() {
@ -30,8 +40,114 @@ void OpenLPClient::showSlides() {
get("/api/display/show"); get("/api/display/show");
} }
void OpenLPClient::changeSong(int it) {
auto n = QString::number(it);
auto url = "/api/service/set?data=%7B%22request%22%3A+%7B%22id%22%3A+" + n + "%7D%7D&_=1627181837297";
get(url);
}
void OpenLPClient::changeSlide(int slide) {
auto n = QString::number(slide);
auto url = R"(/api/controller/live/set?data={"request"%3A+{"id"%3A)" + n + "}}&_=1626628079579)";
get(url);
}
void OpenLPClient::get(QString urlExt) { void OpenLPClient::get(QString urlExt) {
QUrl url(QString(BaseUrl) + urlExt); QUrl url(QString(BaseUrl) + urlExt);
QNetworkRequest rqst(url); QNetworkRequest rqst(url);
m_nam->get(rqst); m_nam->get(rqst);
} }
void OpenLPClient::requestSongList() {
QUrl url(QString(BaseUrl) + "/api/service/list?_=1626628079579");
QNetworkRequest rqst(url);
m_songListNam->get(rqst);
}
void OpenLPClient::requestSlideList() {
QUrl url(QString(BaseUrl) + "/api/controller/live/text?_=1626628079579");
QNetworkRequest rqst(url);
m_slideListNam->get(rqst);
}
void OpenLPClient::poll() {
QUrl url(QString(BaseUrl) + "/api/poll?_=1626628079579");
QNetworkRequest rqst(url);
m_pollingNam->get(rqst);
}
void OpenLPClient::handleGeneralResponse(QNetworkReply *reply) {
if (reply->error()) {
qDebug() << reply->request().url() << ":" << reply->errorString();
}
}
void OpenLPClient::handlePollResponse(QNetworkReply *reply) {
if (reply->error()) {
qDebug() << reply->errorString();
}
auto data = reply->readAll();
if (data.isEmpty()) {
return;
}
auto doc = QJsonDocument::fromJson(data);
auto obj = doc.object()["results"].toObject();
auto songId = obj["item"].toString();
auto slide = obj["slide"].toInt();
auto service = obj["service"].toInt();
if (service != m_currentServiceId) {
requestSongList();
m_currentServiceId = service;
}
if (m_currentSongId != songId) {
requestSlideList();
m_currentSongId = songId;
}
emit pollUpdate(m_songNameMap[songId], slide);
}
void OpenLPClient::handleSongListResponse(QNetworkReply *reply) {
if (reply->error()) {
qDebug() << reply->errorString();
}
auto data = reply->readAll();
if (data.isEmpty()) {
return;
}
QStringList songList;
auto doc = QJsonDocument::fromJson(data);
auto items = doc.object()["results"].toObject()["items"].toArray();
m_songIdMap.clear();
m_songNameMap.clear();
for (const auto &item : items) {
auto song = item.toObject();
auto name = song["title"].toString();
auto id = song["id"].toString();
m_songIdMap[name] = id;
m_songNameMap[id] = name;
songList.push_back(name);
}
emit songListUpdate(songList);
}
void OpenLPClient::handleSlideListResponse(QNetworkReply *reply) {
if (reply->error()) {
qDebug() << reply->errorString();
}
auto data = reply->readAll();
if (data.isEmpty()) {
return;
}
QStringList slideList;
QStringList tagList;
auto doc = QJsonDocument::fromJson(data);
auto items = doc.object()["results"].toObject()["slides"].toArray();
for (const auto &item : items) {
auto slide = item.toObject();
auto text = slide["text"].toString();
auto tag = slide["tag"].toString();
slideList.push_back(text);
tagList.push_back(tag);
}
emit slideListUpdate(tagList, slideList);
}

View File

@ -1,13 +1,27 @@
#pragma once #pragma once
#include <QHash>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QObject> #include <QObject>
#include <QTimer>
class OpenLPClient: public QObject { class OpenLPClient: public QObject {
Q_OBJECT Q_OBJECT
private: private:
struct Song {
QString name;
QString id;
};
static constexpr auto BaseUrl = "http://127.0.0.1:4316"; static constexpr auto BaseUrl = "http://127.0.0.1:4316";
QNetworkAccessManager *m_nam = new QNetworkAccessManager(this); QNetworkAccessManager *m_nam = new QNetworkAccessManager(this);
QNetworkAccessManager *m_pollingNam = new QNetworkAccessManager(this);
QNetworkAccessManager *m_songListNam = new QNetworkAccessManager(this);
QNetworkAccessManager *m_slideListNam = new QNetworkAccessManager(this);
QTimer m_pollTimer;
QHash<QString, QString> m_songIdMap;
QHash<QString, QString> m_songNameMap;
int m_currentServiceId = -1;
QString m_currentSongId;
public: public:
explicit OpenLPClient(QObject *parent = nullptr); explicit OpenLPClient(QObject *parent = nullptr);
@ -25,10 +39,34 @@ class OpenLPClient: public QObject {
void showSlides(); void showSlides();
void changeSong(int it);
void changeSlide(int slide);
private: private:
void get(QString url); void get(QString url);
void requestSongList();
void requestSlideList();
private slots:
void poll();
void handleGeneralResponse(QNetworkReply *reply);
void handlePollResponse(QNetworkReply *reply);
void handleSongListResponse(QNetworkReply *reply);
void handleSlideListResponse(QNetworkReply *reply);
signals: signals:
void pollUpdate(QString songId, int slideNum);
void songListUpdate(QStringList);
void slideListUpdate(QStringList, QStringList);
}; };

View File

@ -1,6 +1,62 @@
#include <QComboBox>
#include <QDebug>
#include <QHeaderView>
#include <QTableWidget>
#include <QVBoxLayout>
#include "slideview.hpp" #include "slideview.hpp"
SlideView::SlideView(QWidget *parent) : QWidget(parent) SlideView::SlideView(QWidget *parent): QWidget(parent) {
{ auto lyt = new QVBoxLayout(this);
m_songSelector = new QComboBox(this);
m_slideTable = new QTableWidget(this);
auto header = m_slideTable->horizontalHeader();
header->setVisible(false);
header->setStretchLastSection(true);
m_slideTable->setSelectionBehavior(QTableWidget::SelectionBehavior::SelectRows);
m_slideTable->setSelectionMode(QTableWidget::SelectionMode::SingleSelection);
m_slideTable->setColumnCount(1);
connect(header, &QHeaderView::sectionResized, m_slideTable, &QTableWidget::resizeRowsToContents);
m_slideTable->resizeRowsToContents();
m_slideTable->verticalHeader()->setDefaultSectionSize(300);
lyt->addWidget(m_songSelector);
lyt->addWidget(m_slideTable);
connect(m_slideTable, &QTableWidget::currentCellChanged, this, &SlideView::slideChanged);
}
void SlideView::pollUpdate(QString songName, int slide) {
if (songName != m_currentSong) {
m_currentSong = songName;
m_songSelector->setCurrentText(songName);
}
if (slide != m_currentSlide) {
m_currentSlide = slide;
m_slideTable->setCurrentCell(slide, 0);
}
}
void SlideView::changeSong(int song) {
if (m_songSelector->currentText() != m_currentSong) {
emit songChanged(song);
}
}
void SlideView::slideListUpdate(QStringList tagList, QStringList slideList) {
m_currentSlide = -1;
m_slideTable->setRowCount(slideList.size());
for (int i = 0; i < slideList.size(); ++i) {
auto txt = slideList[i];
auto item = new QTableWidgetItem(txt);
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
m_slideTable->setItem(i, 0, item);
}
m_slideTable->setVerticalHeaderLabels(tagList);
}
void SlideView::songListUpdate(QStringList songList) {
disconnect(m_songSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSong(int)));
m_songSelector->clear();
m_songSelector->addItems(songList);
changeSong(0);
connect(m_songSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSong(int)));
} }

View File

@ -5,10 +5,27 @@
class SlideView : public QWidget class SlideView : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: private:
explicit SlideView(QWidget *parent = nullptr); class QTableWidget *m_slideTable = nullptr;
class QComboBox *m_songSelector = nullptr;
QString m_currentSong;
int m_currentSlide = -1;
public:
explicit SlideView(QWidget *parent = nullptr);
signals: public slots:
void pollUpdate(QString songId, int slideNum);
void songListUpdate(QStringList songList);
void slideListUpdate(QStringList tagList, QStringList songList);
private slots:
void changeSong(int song);
signals:
void songChanged(int);
void slideChanged(int);
}; };