mirror of
https://github.com/gtalent/sc9k.git
synced 2025-01-23 07:23:38 -06:00
Add viewer of slides in current song and combobox for song selection
This commit is contained in:
parent
a2b8073ce8
commit
f1d16ccd19
@ -1,6 +1,6 @@
|
||||
QT += core gui
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += webenginewidgets widgets
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += network widgets
|
||||
|
||||
CONFIG += c++17
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!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>
|
||||
<data>
|
||||
<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.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="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.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
@ -294,12 +294,14 @@
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></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">C:/Users/avuser/Documents/SlideController/SlideController.pro</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</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.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>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWebEngineView>
|
||||
|
||||
#include "slideview.hpp"
|
||||
#include "mainwindow.hpp"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {
|
||||
@ -14,16 +14,13 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {
|
||||
setWindowTitle(tr("Slide Controller 9000"));
|
||||
const auto mainWidget = new QWidget(this);
|
||||
const auto rootLyt = new QVBoxLayout;
|
||||
const auto viewsLayout = new QHBoxLayout;
|
||||
//const auto viewsLayout = new QHBoxLayout;
|
||||
const auto controlsLayout = new QGridLayout;
|
||||
const auto slideView = new QWebEngineView(mainWidget);
|
||||
const auto slideView = new SlideView(this);
|
||||
setCentralWidget(mainWidget);
|
||||
mainWidget->setLayout(rootLyt);
|
||||
viewsLayout->addWidget(slideView, 1);
|
||||
viewsLayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
rootLyt->addLayout(viewsLayout);
|
||||
rootLyt->addWidget(slideView);
|
||||
rootLyt->addLayout(controlsLayout);
|
||||
slideView->setUrl(QUrl("http://127.0.0.1:4316/main"));
|
||||
// setup slide controls
|
||||
const auto btnPrevSong = new QPushButton(tr("Previous Song (Left)"), 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 btnShowSlides = new QPushButton(tr("Show Slides (.)"), this);
|
||||
rootLyt->addLayout(controlsLayout);
|
||||
controlsLayout->addWidget(btnPrevSong, 0, 0);
|
||||
controlsLayout->addWidget(btnPrevSlide, 0, 1);
|
||||
controlsLayout->addWidget(btnNextSlide, 1, 0);
|
||||
controlsLayout->addWidget(btnPrevSlide, 0, 0);
|
||||
controlsLayout->addWidget(btnNextSlide, 0, 1);
|
||||
controlsLayout->addWidget(btnPrevSong, 1, 0);
|
||||
controlsLayout->addWidget(btnNextSong, 1, 1);
|
||||
controlsLayout->addWidget(btnBlankSlides, 2, 0);
|
||||
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_obsClient, &OBSClient::hideSlides);
|
||||
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
|
||||
const auto btnObsHideSlides = new QPushButton(tr("Hide Slides in OBS (;)"), mainWidget);
|
||||
const auto btnObsShowSlides = new QPushButton(tr("Show Slides in OBS (')"), mainWidget);
|
||||
|
@ -25,7 +25,5 @@ class OBSClient : public QObject
|
||||
private:
|
||||
void get(QString url);
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
|
120
openlpclient.cpp
120
openlpclient.cpp
@ -1,9 +1,19 @@
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValueRef>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include "openlpclient.hpp"
|
||||
|
||||
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() {
|
||||
@ -30,8 +40,114 @@ void OpenLPClient::showSlides() {
|
||||
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) {
|
||||
QUrl url(QString(BaseUrl) + urlExt);
|
||||
QNetworkRequest rqst(url);
|
||||
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);
|
||||
}
|
||||
|
@ -1,13 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
class OpenLPClient: public QObject {
|
||||
Q_OBJECT
|
||||
private:
|
||||
struct Song {
|
||||
QString name;
|
||||
QString id;
|
||||
};
|
||||
static constexpr auto BaseUrl = "http://127.0.0.1:4316";
|
||||
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:
|
||||
explicit OpenLPClient(QObject *parent = nullptr);
|
||||
@ -25,10 +39,34 @@ class OpenLPClient: public QObject {
|
||||
|
||||
void showSlides();
|
||||
|
||||
void changeSong(int it);
|
||||
|
||||
void changeSlide(int slide);
|
||||
|
||||
private:
|
||||
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:
|
||||
void pollUpdate(QString songId, int slideNum);
|
||||
|
||||
void songListUpdate(QStringList);
|
||||
|
||||
void slideListUpdate(QStringList, QStringList);
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,62 @@
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QHeaderView>
|
||||
#include <QTableWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#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)));
|
||||
}
|
||||
|
@ -5,10 +5,27 @@
|
||||
class SlideView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SlideView(QWidget *parent = nullptr);
|
||||
private:
|
||||
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);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user