mirror of
https://github.com/gtalent/sc9k.git
synced 2025-07-02 07:11:45 -05:00
Switch from QMake to CMake with buildcore
This commit is contained in:
31
src/CMakeLists.txt
Normal file
31
src/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Network Widgets REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Network Widgets REQUIRED)
|
||||
|
||||
add_executable(
|
||||
SlideController MACOSX_BUNDLE
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
obsclient.cpp
|
||||
openlpclient.cpp
|
||||
slideview.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
SlideController
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
SlideController
|
||||
DESTINATION
|
||||
bin
|
||||
BUNDLE DESTINATION .
|
||||
)
|
||||
|
11
src/consts.hpp
Normal file
11
src/consts.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
constexpr auto SlideHost = "turbo";
|
18
src/main.cpp
Normal file
18
src/main.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "mainwindow.hpp"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
118
src/mainwindow.cpp
Normal file
118
src/mainwindow.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QStatusBar>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "slideview.hpp"
|
||||
#include "mainwindow.hpp"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {
|
||||
move(0, 0);
|
||||
setFixedSize(590, 555);
|
||||
setWindowTitle(tr("Slide Controller 9000"));
|
||||
const auto mainWidget = new QWidget(this);
|
||||
const auto rootLyt = new QVBoxLayout;
|
||||
const auto controlsLayout = new QGridLayout;
|
||||
const auto slideView = new SlideView(this);
|
||||
setCentralWidget(mainWidget);
|
||||
mainWidget->setLayout(rootLyt);
|
||||
rootLyt->addWidget(slideView);
|
||||
rootLyt->addLayout(controlsLayout);
|
||||
// setup slide controls
|
||||
const auto btnPrevSong = new QPushButton(tr("Previous Song (Left)"), this);
|
||||
const auto btnPrevSlide = new QPushButton(tr("Previous Slide (Up)"), this);
|
||||
const auto btnNextSlide = new QPushButton(tr("Next Slide (Down)"), this);
|
||||
const auto btnNextSong = new QPushButton(tr("Next Song (Right))"), this);
|
||||
const auto btnBlankSlides = new QPushButton(tr("Blank Slides (,)"), this);
|
||||
const auto btnShowSlides = new QPushButton(tr("Show Slides (.)"), this);
|
||||
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);
|
||||
btnNextSong->setShortcut(Qt::Key_Right);
|
||||
btnPrevSong->setShortcut(Qt::Key_Left);
|
||||
btnNextSlide->setShortcut(Qt::Key_Down);
|
||||
btnPrevSlide->setShortcut(Qt::Key_Up);
|
||||
btnBlankSlides->setShortcut(Qt::Key_Comma);
|
||||
btnShowSlides->setShortcut(Qt::Key_Period);
|
||||
btnBlankSlides->setToolTip(tr("Also hides slides in OBS"));
|
||||
connect(btnNextSlide, &QPushButton::clicked, &m_openlpClient, &OpenLPClient::nextSlide);
|
||||
connect(btnPrevSlide, &QPushButton::clicked, &m_openlpClient, &OpenLPClient::prevSlide);
|
||||
connect(btnNextSong, &QPushButton::clicked, &m_openlpClient, &OpenLPClient::nextSong);
|
||||
connect(btnPrevSong, &QPushButton::clicked, &m_openlpClient, &OpenLPClient::prevSong);
|
||||
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(&m_openlpClient, &OpenLPClient::pollFailed, slideView, &SlideView::reset);
|
||||
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);
|
||||
controlsLayout->addWidget(btnObsHideSlides, 3, 0);
|
||||
controlsLayout->addWidget(btnObsShowSlides, 3, 1);
|
||||
btnObsHideSlides->setShortcut(Qt::Key_Semicolon);
|
||||
btnObsShowSlides->setShortcut(Qt::Key_Apostrophe);
|
||||
btnObsShowSlides->setToolTip(tr("Also shows slides in OpenLP"));
|
||||
connect(btnObsHideSlides, &QPushButton::clicked, &m_obsClient, &OBSClient::hideSlides);
|
||||
connect(btnObsShowSlides, &QPushButton::clicked, &m_obsClient, &OBSClient::showSlides);
|
||||
connect(btnObsShowSlides, &QPushButton::clicked, &m_openlpClient, &OpenLPClient::showSlides);
|
||||
// setup status bar
|
||||
setStatusBar(new QStatusBar(this));
|
||||
connect(&m_openlpClient, &OpenLPClient::pollUpdate, this, &MainWindow::openLpConnectionInit);
|
||||
connect(&m_obsClient, &OBSClient::pollUpdate, this, &MainWindow::obsConnectionInit);
|
||||
refreshStatusBar();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
}
|
||||
|
||||
void MainWindow::openLpConnectionInit() {
|
||||
disconnect(&m_openlpClient, &OpenLPClient::pollUpdate, this, &MainWindow::openLpConnectionInit);
|
||||
connect(&m_openlpClient, &OpenLPClient::pollFailed, this, &MainWindow::openLpConnectionLost);
|
||||
m_openLpConnected = true;
|
||||
refreshStatusBar();
|
||||
}
|
||||
|
||||
void MainWindow::openLpConnectionLost() {
|
||||
disconnect(&m_openlpClient, &OpenLPClient::pollFailed, this, &MainWindow::openLpConnectionLost);
|
||||
connect(&m_openlpClient, &OpenLPClient::pollUpdate, this, &MainWindow::openLpConnectionInit);
|
||||
m_openLpConnected = false;
|
||||
refreshStatusBar();
|
||||
}
|
||||
|
||||
void MainWindow::obsConnectionInit() {
|
||||
disconnect(&m_obsClient, &OBSClient::pollUpdate, this, &MainWindow::obsConnectionInit);
|
||||
connect(&m_obsClient, &OBSClient::pollFailed, this, &MainWindow::obsConnectionLost);
|
||||
m_obsConnected = true;
|
||||
refreshStatusBar();
|
||||
}
|
||||
|
||||
void MainWindow::obsConnectionLost() {
|
||||
disconnect(&m_obsClient, &OBSClient::pollFailed, this, &MainWindow::obsConnectionLost);
|
||||
connect(&m_obsClient, &OBSClient::pollUpdate, this, &MainWindow::obsConnectionInit);
|
||||
m_obsConnected = false;
|
||||
refreshStatusBar();
|
||||
}
|
||||
|
||||
void MainWindow::refreshStatusBar() {
|
||||
const auto openLpStatus = m_openLpConnected ? tr("OpenLP: Connected") : tr("OpenLP: Not Connected");
|
||||
const auto obsStatus = m_obsConnected ? tr("OBS: Connected") : tr("OBS: Not Connected");
|
||||
statusBar()->showMessage(openLpStatus + " | " + obsStatus);
|
||||
}
|
42
src/mainwindow.hpp
Normal file
42
src/mainwindow.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "obsclient.hpp"
|
||||
#include "openlpclient.hpp"
|
||||
|
||||
class MainWindow: public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OBSClient m_obsClient;
|
||||
OpenLPClient m_openlpClient;
|
||||
bool m_openLpConnected = false;
|
||||
bool m_obsConnected = false;
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
private slots:
|
||||
void openLpConnectionInit();
|
||||
|
||||
void openLpConnectionLost();
|
||||
|
||||
void obsConnectionInit();
|
||||
|
||||
void obsConnectionLost();
|
||||
|
||||
void refreshStatusBar();
|
||||
|
||||
};
|
60
src/obsclient.cpp
Normal file
60
src/obsclient.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QUrl>
|
||||
|
||||
#include "obsclient.hpp"
|
||||
|
||||
OBSClient::OBSClient(QObject *parent): QObject(parent) {
|
||||
m_pollTimer.start(1000);
|
||||
connect(&m_pollTimer, &QTimer::timeout, this, &OBSClient::poll);
|
||||
connect(m_pollingNam, &QNetworkAccessManager::finished, this, &OBSClient::handlePollResponse);
|
||||
}
|
||||
|
||||
void OBSClient::setScene(QString scene) {
|
||||
get(QString("/Scene?name=%1").arg(scene));
|
||||
}
|
||||
|
||||
void OBSClient::showSlides() {
|
||||
setScene("MusicScene");
|
||||
}
|
||||
|
||||
void OBSClient::hideSlides() {
|
||||
setScene("SpeakerScene");
|
||||
}
|
||||
|
||||
void OBSClient::setSlidesVisible(int state) {
|
||||
if (state) {
|
||||
setScene("MusicScene");
|
||||
} else {
|
||||
setScene("SpeakerScene");
|
||||
}
|
||||
}
|
||||
|
||||
void OBSClient::get(QString urlExt) {
|
||||
QUrl url(QString(BaseUrl) + urlExt);
|
||||
QNetworkRequest rqst(url);
|
||||
m_nam->get(rqst);
|
||||
}
|
||||
|
||||
void OBSClient::poll() {
|
||||
QUrl url(QString(BaseUrl) + "/ping");
|
||||
QNetworkRequest rqst(url);
|
||||
m_pollingNam->get(rqst);
|
||||
}
|
||||
|
||||
void OBSClient::handlePollResponse(QNetworkReply *reply) {
|
||||
if (reply->error()) {
|
||||
qDebug() << "OBSClient error response:" << reply->errorString();
|
||||
emit pollFailed();
|
||||
return;
|
||||
}
|
||||
emit pollUpdate();
|
||||
}
|
||||
|
50
src/obsclient.hpp
Normal file
50
src/obsclient.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include "consts.hpp"
|
||||
|
||||
class OBSClient: public QObject {
|
||||
Q_OBJECT
|
||||
private:
|
||||
const QString BaseUrl = QString("http://") + SlideHost + ":9302";
|
||||
QNetworkAccessManager *m_nam = new QNetworkAccessManager(this);
|
||||
QNetworkAccessManager *m_pollingNam = new QNetworkAccessManager(this);
|
||||
QTimer m_pollTimer;
|
||||
|
||||
public:
|
||||
explicit OBSClient(QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void setScene(QString scene);
|
||||
|
||||
void showSlides();
|
||||
|
||||
void hideSlides();
|
||||
|
||||
void setSlidesVisible(int state);
|
||||
|
||||
private:
|
||||
void get(QString url);
|
||||
|
||||
void poll();
|
||||
|
||||
void handlePollResponse(QNetworkReply *reply);
|
||||
|
||||
signals:
|
||||
void pollUpdate();
|
||||
|
||||
void pollFailed();
|
||||
|
||||
};
|
||||
|
164
src/openlpclient.cpp
Normal file
164
src/openlpclient.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValueRef>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include "openlpclient.hpp"
|
||||
|
||||
OpenLPClient::OpenLPClient(QObject *parent): QObject(parent) {
|
||||
poll();
|
||||
m_pollTimer.start(250);
|
||||
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() {
|
||||
get("/api/controller/live/next");
|
||||
}
|
||||
|
||||
void OpenLPClient::prevSlide() {
|
||||
get("/api/controller/live/previous");
|
||||
}
|
||||
|
||||
void OpenLPClient::nextSong() {
|
||||
get("/api/service/next");
|
||||
}
|
||||
|
||||
void OpenLPClient::prevSong() {
|
||||
get("/api/service/previous");
|
||||
}
|
||||
|
||||
void OpenLPClient::blankScreen() {
|
||||
get("/api/display/hide");
|
||||
}
|
||||
|
||||
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() << "OpenLPClient error response:" << reply->request().url() << ":" << reply->errorString();
|
||||
}
|
||||
}
|
||||
|
||||
void OpenLPClient::handlePollResponse(QNetworkReply *reply) {
|
||||
if (reply->error()) {
|
||||
qDebug() << "OpenLPClient error response:" << reply->errorString();
|
||||
emit pollFailed();
|
||||
m_currentServiceId = -1;
|
||||
m_currentSongId = "";
|
||||
m_songNameMap.clear();
|
||||
return;
|
||||
}
|
||||
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() << "OpenLPClient error response:" << 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_songNameMap.clear();
|
||||
for (const auto &item : items) {
|
||||
auto song = item.toObject();
|
||||
auto name = song["title"].toString();
|
||||
auto id = song["id"].toString();
|
||||
m_songNameMap[id] = name;
|
||||
songList.push_back(name);
|
||||
}
|
||||
emit songListUpdate(songList);
|
||||
}
|
||||
|
||||
void OpenLPClient::handleSlideListResponse(QNetworkReply *reply) {
|
||||
if (reply->error()) {
|
||||
qDebug() << "OpenLPClient error response:" << 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);
|
||||
}
|
84
src/openlpclient.hpp
Normal file
84
src/openlpclient.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include "consts.hpp"
|
||||
|
||||
class OpenLPClient: public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
struct Song {
|
||||
QString name;
|
||||
QString id;
|
||||
};
|
||||
const QString BaseUrl = QString("http://") + SlideHost + ":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_songNameMap;
|
||||
int m_currentServiceId = -1;
|
||||
QString m_currentSongId;
|
||||
|
||||
public:
|
||||
explicit OpenLPClient(QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void nextSlide();
|
||||
|
||||
void prevSlide();
|
||||
|
||||
void nextSong();
|
||||
|
||||
void prevSong();
|
||||
|
||||
void blankScreen();
|
||||
|
||||
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 pollFailed();
|
||||
|
||||
void songListUpdate(QStringList);
|
||||
|
||||
void slideListUpdate(QStringList, QStringList);
|
||||
|
||||
};
|
||||
|
85
src/slideview.cpp
Normal file
85
src/slideview.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QHeaderView>
|
||||
#include <QTableWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "slideview.hpp"
|
||||
|
||||
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);
|
||||
m_slideTable->verticalHeader()->setDefaultSectionSize(300);
|
||||
#ifndef _WIN32
|
||||
m_slideTable->setAlternatingRowColors(true);
|
||||
#endif
|
||||
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 = 0;
|
||||
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);
|
||||
m_slideTable->resizeRowsToContents();
|
||||
}
|
||||
|
||||
void SlideView::reset() {
|
||||
m_songSelector->clear();
|
||||
m_slideTable->setRowCount(0);
|
||||
m_currentSong = "";
|
||||
m_currentSlide = -1;
|
||||
}
|
||||
|
||||
void SlideView::songListUpdate(QStringList songList) {
|
||||
// Is this replacing an existing song list or is it the initial song list?
|
||||
// We want to reset the song to 0 upon replacement,
|
||||
// but leave it alone upon initialization.
|
||||
auto isReplacement = m_songSelector->count() > 0;
|
||||
disconnect(m_songSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSong(int)));
|
||||
m_songSelector->clear();
|
||||
m_songSelector->addItems(songList);
|
||||
if (isReplacement) {
|
||||
changeSong(0);
|
||||
}
|
||||
connect(m_songSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(changeSong(int)));
|
||||
}
|
39
src/slideview.hpp
Normal file
39
src/slideview.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class SlideView: public QWidget {
|
||||
Q_OBJECT
|
||||
private:
|
||||
class QTableWidget *m_slideTable = nullptr;
|
||||
class QComboBox *m_songSelector = nullptr;
|
||||
QString m_currentSong;
|
||||
int m_currentSlide = -1;
|
||||
public:
|
||||
explicit SlideView(QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void pollUpdate(QString songId, int slideNum);
|
||||
|
||||
void songListUpdate(QStringList songList);
|
||||
|
||||
void slideListUpdate(QStringList tagList, QStringList songList);
|
||||
|
||||
void reset();
|
||||
|
||||
private slots:
|
||||
void changeSong(int song);
|
||||
|
||||
signals:
|
||||
void songChanged(int);
|
||||
|
||||
void slideChanged(int);
|
||||
};
|
||||
|
Reference in New Issue
Block a user