mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-11-10 13:44:17 +00:00
Start GUI rewrite in QML
This commit is contained in:
parent
04c9a3a2eb
commit
6a3b95a4b1
11 changed files with 106 additions and 325 deletions
33
app/app.pro
33
app/app.pro
|
@ -1,12 +1,8 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2018-04-28T14:01:01
|
||||
#
|
||||
#-------------------------------------------------
|
||||
QT += core quick network
|
||||
CONFIG += c++11
|
||||
|
||||
QT += core gui network
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
# TODO: Rid ourselves of QtWidgets
|
||||
QT += widgets
|
||||
|
||||
TARGET = moonlight-qt
|
||||
TEMPLATE = app
|
||||
|
@ -52,8 +48,6 @@ win32 {
|
|||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
gui/mainwindow.cpp \
|
||||
gui/popupmanager.cpp \
|
||||
backend/identitymanager.cpp \
|
||||
backend/nvhttp.cpp \
|
||||
backend/nvpairingmanager.cpp \
|
||||
|
@ -67,8 +61,6 @@ SOURCES += \
|
|||
|
||||
HEADERS += \
|
||||
utils.h \
|
||||
gui/mainwindow.h \
|
||||
gui/popupmanager.h \
|
||||
backend/identitymanager.h \
|
||||
backend/nvhttp.h \
|
||||
backend/nvpairingmanager.h \
|
||||
|
@ -78,11 +70,15 @@ HEADERS += \
|
|||
streaming/input.hpp \
|
||||
streaming/session.hpp
|
||||
|
||||
FORMS += \
|
||||
gui/mainwindow.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc
|
||||
resources.qrc \
|
||||
qml.qrc
|
||||
|
||||
# Additional import path used to resolve QML modules in Qt Creator's code model
|
||||
QML_IMPORT_PATH =
|
||||
|
||||
# Additional import path used to resolve QML modules just for Qt Quick Designer
|
||||
QML_DESIGNER_IMPORT_PATH =
|
||||
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../moonlight-common-c/release/ -lmoonlight-common-c
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../moonlight-common-c/debug/ -lmoonlight-common-c
|
||||
|
@ -104,3 +100,8 @@ else:unix: LIBS += -L$$OUT_PWD/../qmdnsengine/ -lqmdnsengine
|
|||
|
||||
INCLUDEPATH += $$PWD/../qmdnsengine/qmdnsengine/src/include $$PWD/../qmdnsengine
|
||||
DEPENDPATH += $$PWD/../qmdnsengine/qmdnsengine/src/include $$PWD/../qmdnsengine
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
|
|
65
app/gui/main.qml
Normal file
65
app/gui/main.qml
Normal file
|
@ -0,0 +1,65 @@
|
|||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
ApplicationWindow {
|
||||
id: window
|
||||
visible: true
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("Stack")
|
||||
|
||||
header: ToolBar {
|
||||
contentHeight: toolButton.implicitHeight
|
||||
|
||||
ToolButton {
|
||||
id: toolButton
|
||||
text: stackView.depth > 1 ? "\u25C0" : "\u2630"
|
||||
font.pixelSize: Qt.application.font.pixelSize * 1.6
|
||||
onClicked: {
|
||||
if (stackView.depth > 1) {
|
||||
stackView.pop()
|
||||
} else {
|
||||
drawer.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: stackView.currentItem.title
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
Drawer {
|
||||
id: drawer
|
||||
width: window.width * 0.66
|
||||
height: window.height
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
|
||||
ItemDelegate {
|
||||
text: qsTr("Page 1")
|
||||
width: parent.width
|
||||
onClicked: {
|
||||
stackView.push("Page1Form.ui.qml")
|
||||
drawer.close()
|
||||
}
|
||||
}
|
||||
ItemDelegate {
|
||||
text: qsTr("Page 2")
|
||||
width: parent.width
|
||||
onClicked: {
|
||||
stackView.push("Page2Form.ui.qml")
|
||||
drawer.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StackView {
|
||||
id: stackView
|
||||
initialItem: "HomeForm.ui.qml"
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
#include "gui/mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "gui/popupmanager.h"
|
||||
#include "backend/identitymanager.h"
|
||||
#include "backend/nvpairingmanager.h"
|
||||
#include "streaming/session.hpp"
|
||||
#include "backend/computermanager.h"
|
||||
#include "backend/boxartmanager.h"
|
||||
#include "settings/streamingpreferences.h"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow),
|
||||
m_BoxArtManager(this),
|
||||
m_ComputerManager(this)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(&m_BoxArtManager, SIGNAL(boxArtLoadComplete(NvComputer*,NvApp,QImage)),
|
||||
this, SLOT(boxArtLoadComplete(NvComputer*,NvApp,QImage)));
|
||||
connect(&m_ComputerManager, SIGNAL(computerStateChanged(NvComputer*)),
|
||||
this, SLOT(computerStateChanged(NvComputer*)));
|
||||
m_ComputerManager.startPolling();
|
||||
qDebug() << "Cached computers: " << m_ComputerManager.getComputers().count();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::boxArtLoadComplete(NvComputer* computer, NvApp app, QImage image)
|
||||
{
|
||||
qDebug() << "Loaded image";
|
||||
}
|
||||
|
||||
void MainWindow::on_actionExit_triggered()
|
||||
{
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
void MainWindow::computerStateChanged(NvComputer* computer)
|
||||
{
|
||||
QReadLocker lock(&computer->lock);
|
||||
|
||||
NvHTTP http(computer->activeAddress);
|
||||
|
||||
if (computer->pairState == NvComputer::PS_NOT_PAIRED) {
|
||||
NvPairingManager pm(computer->activeAddress);
|
||||
QString pin = pm.generatePinString();
|
||||
pm.pair(http.getServerInfo(), pin);
|
||||
}
|
||||
else if (!computer->appList.isEmpty()) {
|
||||
QImage im = m_BoxArtManager.loadBoxArt(computer, computer->appList[0]);
|
||||
|
||||
// Stop polling before launching a game
|
||||
m_ComputerManager.stopPollingAsync();
|
||||
|
||||
Session session(computer, computer->appList.last());
|
||||
QStringList warnings;
|
||||
QString errorMessage;
|
||||
|
||||
// First check for a fatal configuration error
|
||||
errorMessage = session.checkForFatalValidationError();
|
||||
if (!errorMessage.isEmpty()) {
|
||||
// TODO: display error dialog
|
||||
goto AfterStreaming;
|
||||
}
|
||||
|
||||
// Check for any informational messages to display
|
||||
warnings = session.checkForAdvisoryValidationError();
|
||||
if (!warnings.isEmpty()) {
|
||||
// TODO: display toast or something before we start
|
||||
}
|
||||
|
||||
// Run the streaming session until termination
|
||||
session.exec();
|
||||
|
||||
AfterStreaming:
|
||||
m_ComputerManager.startPolling();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_newHostBtn_clicked()
|
||||
{
|
||||
QString hostname = popupmanager::getHostnameDialog(this);
|
||||
if (!hostname.isEmpty()) {
|
||||
m_ComputerManager.addNewHost(hostname, false);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::addHostToDisplay(QMap<QString, bool> hostMdnsMap) {
|
||||
|
||||
QMapIterator<QString, bool> i(hostMdnsMap);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
ui->hostSelectCombo->addItem(i.key());
|
||||
// we can ignore the mdns for now, it's only useful for displaying unpairing options
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_selectHostComboBox_activated(const QString &selectedHostname)
|
||||
{
|
||||
// TODO: get all the applications that "selectedHostname" has listed
|
||||
// probably populate another combobox of applications for the time being
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include "backend/computermanager.h"
|
||||
#include "backend/boxartmanager.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QtWidgets>
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
private slots:
|
||||
void on_actionExit_triggered();
|
||||
void on_newHostBtn_clicked();
|
||||
void addHostToDisplay(QMap<QString, bool>);
|
||||
void on_selectHostComboBox_activated(const QString &);
|
||||
void computerStateChanged(NvComputer* computer);
|
||||
void boxArtLoadComplete(NvComputer* computer, NvApp app, QImage image);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
BoxArtManager m_BoxArtManager;
|
||||
ComputerManager m_ComputerManager;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
|
@ -1,102 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>483</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<widget class="QWidget" name="gridLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>50</x>
|
||||
<y>30</y>
|
||||
<width>306</width>
|
||||
<height>191</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="newHostBtn">
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add New Host</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/res/icon128.png</normaloff>:/res/icon128.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="hostSelectCombo"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionSettings"/>
|
||||
<addaction name="actionGamepad_Mapping"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
</widget>
|
||||
<action name="actionSettings">
|
||||
<property name="text">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGamepad_Mapping">
|
||||
<property name="text">
|
||||
<string>Gamepad Mapping</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit">
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,41 +0,0 @@
|
|||
#include "popupmanager.h"
|
||||
|
||||
QMessageBox *popupmanager::pinMsgBox = nullptr;
|
||||
|
||||
popupmanager::popupmanager(){}
|
||||
|
||||
// this opens a non-blocking informative message telling the user to enter the given pin
|
||||
// it is open-loop: if the user cancels, nothing happens
|
||||
// it is expected that upon pairing completion, the ::closePinDialog function will be called.
|
||||
void popupmanager::displayPinDialog(QString pin, QWidget* parent) {
|
||||
|
||||
popupmanager::pinMsgBox = new QMessageBox( parent );
|
||||
popupmanager::pinMsgBox->setAttribute( Qt::WA_DeleteOnClose ); //makes sure the msgbox is deleted automatically when closed
|
||||
popupmanager::pinMsgBox->setStandardButtons( QMessageBox::Ok );
|
||||
popupmanager::pinMsgBox->setText("Please enter the number " + pin + " on the GFE dialog on the computer.");
|
||||
popupmanager::pinMsgBox->setInformativeText("This dialog will be dismissed once complete.");
|
||||
popupmanager::pinMsgBox->open();
|
||||
}
|
||||
|
||||
// to be called when the pairing is complete
|
||||
void popupmanager::closePinDialog() {
|
||||
pinMsgBox->close();
|
||||
delete pinMsgBox;
|
||||
}
|
||||
|
||||
QString popupmanager::getHostnameDialog(QWidget* parent) {
|
||||
bool ok;
|
||||
QString responseHost
|
||||
= QInputDialog::getText(parent, QObject::tr("Add Host Manually"),
|
||||
QObject::tr("IP Address or Hostname of GeForce PC"),
|
||||
QLineEdit::Normal,
|
||||
QObject::tr("default string"),
|
||||
&ok);
|
||||
if (ok && !responseHost.isEmpty()) {
|
||||
return responseHost;
|
||||
} else {
|
||||
return QObject::tr("");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef POPUPMANAGER_H
|
||||
#define POPUPMANAGER_H
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
class popupmanager
|
||||
{
|
||||
public:
|
||||
popupmanager();
|
||||
static void displayPinDialog(QString pin, QWidget* parent);
|
||||
static void closePinDialog();
|
||||
static QString getHostnameDialog(QWidget* parent);
|
||||
|
||||
private:
|
||||
static QMessageBox *pinMsgBox;
|
||||
};
|
||||
|
||||
#endif // POPUPMANAGER_H
|
6
app/gui/qtquickcontrols2.conf
Normal file
6
app/gui/qtquickcontrols2.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
; This file can be edited to change the style of the application
|
||||
; Read "Qt Quick Controls 2 Configuration File" for details:
|
||||
; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html
|
||||
|
||||
[Controls]
|
||||
Style=Imagine
|
18
app/main.cpp
18
app/main.cpp
|
@ -1,5 +1,5 @@
|
|||
#include "gui/mainwindow.h"
|
||||
#include <QApplication>
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
#include "backend/nvhttp.h"
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
|
||||
// This avoids using the default keychain for SSL, which may cause
|
||||
// password prompts on macOS.
|
||||
qputenv("QT_SSL_USE_TEMPORARY_KEYCHAIN", QByteArray("1"));
|
||||
|
@ -22,9 +24,13 @@ int main(int argc, char *argv[])
|
|||
// Register custom metatypes for use in signals
|
||||
qRegisterMetaType<NvApp>("NvApp");
|
||||
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
// Load the main.qml file
|
||||
QQmlApplicationEngine engine;
|
||||
engine.load(QUrl(QStringLiteral("qrc:/gui/main.qml")));
|
||||
if (engine.rootObjects().isEmpty())
|
||||
return -1;
|
||||
|
||||
// Ensure that SDL is always initialized since we may need to use it
|
||||
// for non-streaming purposes (like checking on audio devices)
|
||||
|
@ -37,7 +43,7 @@ int main(int argc, char *argv[])
|
|||
SDL_GetError());
|
||||
}
|
||||
|
||||
int err = a.exec();
|
||||
int err = app.exec();
|
||||
|
||||
SDL_Quit();
|
||||
|
||||
|
|
6
app/qml.qrc
Normal file
6
app/qml.qrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>gui/main.qml</file>
|
||||
<file>gui/qtquickcontrols2.conf</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include <QMessageBox>
|
||||
|
||||
|
||||
class Session
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in a new issue