mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-06-17 14:11:33 +00:00
Implement support for quitting apps
This commit is contained in:
@@ -51,6 +51,7 @@ NvComputer::NvComputer(QSettings& settings)
|
|||||||
this->appVersion = nullptr;
|
this->appVersion = nullptr;
|
||||||
this->maxLumaPixelsHEVC = 0;
|
this->maxLumaPixelsHEVC = 0;
|
||||||
this->serverCodecModeSupport = 0;
|
this->serverCodecModeSupport = 0;
|
||||||
|
this->pendingQuit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -135,6 +136,7 @@ NvComputer::NvComputer(QString address, QString serverInfo)
|
|||||||
this->gfeVersion = NvHTTP::getXmlString(serverInfo, "GfeVersion");
|
this->gfeVersion = NvHTTP::getXmlString(serverInfo, "GfeVersion");
|
||||||
this->activeAddress = address;
|
this->activeAddress = address;
|
||||||
this->state = NvComputer::CS_ONLINE;
|
this->state = NvComputer::CS_ONLINE;
|
||||||
|
this->pendingQuit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NvComputer::wake()
|
bool NvComputer::wake()
|
||||||
@@ -508,7 +510,7 @@ ComputerManager::handleComputerStateChanged(NvComputer* computer)
|
|||||||
|
|
||||||
if (computer->pendingQuit && computer->currentGameId == 0) {
|
if (computer->pendingQuit && computer->currentGameId == 0) {
|
||||||
computer->pendingQuit = false;
|
computer->pendingQuit = false;
|
||||||
emit quitAppCompleted(nullptr);
|
emit quitAppCompleted(QVariant());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save updated hosts to QSettings
|
// Save updated hosts to QSettings
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ signals:
|
|||||||
|
|
||||||
void computerAddCompleted(QVariant success);
|
void computerAddCompleted(QVariant success);
|
||||||
|
|
||||||
void quitAppCompleted(QString error);
|
void quitAppCompleted(QVariant error);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleComputerStateChanged(NvComputer* computer);
|
void handleComputerStateChanged(NvComputer* computer);
|
||||||
|
|||||||
+86
-13
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick 2.9
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
import QtQuick.Controls 2.2
|
import QtQuick.Controls 2.2
|
||||||
|
|
||||||
import AppModel 1.0
|
import AppModel 1.0
|
||||||
@@ -50,12 +51,6 @@ GridView {
|
|||||||
delegate: Item {
|
delegate: Item {
|
||||||
width: 200; height: 300;
|
width: 200; height: 300;
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (model.running) {
|
|
||||||
appNameText.text = "<font color=\"green\">Running</font><font color=\"white\"> - </font>" + appNameText.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: appIcon
|
id: appIcon
|
||||||
anchors.horizontalCenter: parent.horizontalCenter;
|
anchors.horizontalCenter: parent.horizontalCenter;
|
||||||
@@ -68,7 +63,15 @@ GridView {
|
|||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: appNameText
|
id: appNameText
|
||||||
text: model.name
|
text: {
|
||||||
|
if (model.running) {
|
||||||
|
return "<font color=\"green\">Running</font><font color=\"white\"> - </font>" + model.name
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return model.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
color: "white"
|
color: "white"
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -80,16 +83,86 @@ GridView {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function launchOrResumeSelectedApp()
|
||||||
|
{
|
||||||
|
var runningIndex = appModel.getRunningAppIndex()
|
||||||
|
if (runningIndex >= 0 && runningIndex !== index) {
|
||||||
|
quitAppDialog.appName = appModel.getRunningAppName()
|
||||||
|
quitAppDialog.segueToStream = true
|
||||||
|
quitAppDialog.open()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var component = Qt.createComponent("StreamSegue.qml")
|
||||||
|
var segue = component.createObject(stackView)
|
||||||
|
segue.appName = model.name
|
||||||
|
segue.session = appModel.createSessionForApp(index)
|
||||||
|
stackView.push(segue)
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageDialog {
|
||||||
|
id: quitAppDialog
|
||||||
|
modality:Qt.WindowModal
|
||||||
|
property string appName : "";
|
||||||
|
property bool segueToStream : false
|
||||||
|
text:"Are you sure you want to quit " + appName +"? Any unsaved progress will be lost."
|
||||||
|
standardButtons: StandardButton.Yes | StandardButton.No
|
||||||
|
onYes: {
|
||||||
|
var component = Qt.createComponent("QuitSegue.qml")
|
||||||
|
var segue = component.createObject(stackView)
|
||||||
|
segue.appName = appName
|
||||||
|
if (segueToStream) {
|
||||||
|
// Store the session and app name if we're going to stream after
|
||||||
|
// successfully quitting the old app.
|
||||||
|
segue.nextAppName = model.name
|
||||||
|
segue.nextSession = appModel.createSessionForApp(index)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
segue.nextAppName = null
|
||||||
|
segue.nextSession = null
|
||||||
|
}
|
||||||
|
|
||||||
|
stackView.push(segue)
|
||||||
|
|
||||||
|
// Trigger the quit after pushing the quit segue on screen
|
||||||
|
appModel.quitRunningApp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
onClicked: {
|
onClicked: {
|
||||||
// TODO: Check if a different game is running
|
if (mouse.button === Qt.LeftButton) {
|
||||||
|
// Nothing is running or this app is running
|
||||||
|
launchOrResumeSelectedApp()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Right click
|
||||||
|
appContextMenu.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var component = Qt.createComponent("StreamSegue.qml")
|
Menu {
|
||||||
var segue = component.createObject(stackView)
|
id: appContextMenu
|
||||||
segue.appname = model.name
|
MenuItem {
|
||||||
segue.session = appModel.createSessionForApp(index)
|
text: model.running ? "Resume Game" : "Launch Game"
|
||||||
stackView.push(segue)
|
onTriggered: {
|
||||||
|
appContextMenu.close()
|
||||||
|
launchOrResumeSelectedApp()
|
||||||
|
}
|
||||||
|
height: visible ? implicitHeight : 0
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: "Quit Game"
|
||||||
|
onTriggered: {
|
||||||
|
quitAppDialog.appName = appModel.getRunningAppName()
|
||||||
|
quitAppDialog.segueToStream = false
|
||||||
|
quitAppDialog.open()
|
||||||
|
}
|
||||||
|
visible: model.running
|
||||||
|
height: visible ? implicitHeight : 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
|
|
||||||
|
import ComputerManager 1.0
|
||||||
|
import Session 1.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property string appName
|
||||||
|
property Session nextSession : null
|
||||||
|
property string nextAppName : ""
|
||||||
|
|
||||||
|
property string stageText : "Quitting " + appName + "..."
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
// The StackView will trigger a visibility change when
|
||||||
|
// we're pushed onto it, causing our onVisibleChanged
|
||||||
|
// routine to run, but only if we start as invisible
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
function quitAppCompleted(error)
|
||||||
|
{
|
||||||
|
// Display a failed dialog if we got an error
|
||||||
|
if (error !== undefined) {
|
||||||
|
errorDialog.text = error
|
||||||
|
errorDialog.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit this view
|
||||||
|
stackView.pop()
|
||||||
|
|
||||||
|
// If we're supposed to launch another game after this, do so now
|
||||||
|
if (error === undefined && nextSession !== null) {
|
||||||
|
var component = Qt.createComponent("StreamSegue.qml")
|
||||||
|
var segue = component.createObject(stackView)
|
||||||
|
segue.appName = nextAppName
|
||||||
|
segue.session = nextSession
|
||||||
|
stackView.push(segue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (visible) {
|
||||||
|
// Connect the quit completion signal
|
||||||
|
ComputerManager.quitAppCompleted.connect(quitAppCompleted)
|
||||||
|
|
||||||
|
// We must be polling or we won't get the quitAppCompleted() callback
|
||||||
|
ComputerManager.startPolling()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Disconnect the signal
|
||||||
|
ComputerManager.quitAppCompleted.disconnect(quitAppCompleted)
|
||||||
|
|
||||||
|
// Stop polling when this view is not on top
|
||||||
|
ComputerManager.stopPollingAsync()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: 5
|
||||||
|
|
||||||
|
BusyIndicator {
|
||||||
|
id: stageSpinner
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: stageLabel
|
||||||
|
height: stageSpinner.height
|
||||||
|
text: stageText
|
||||||
|
font.pointSize: 20
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageDialog {
|
||||||
|
id: errorDialog
|
||||||
|
modality:Qt.WindowModal
|
||||||
|
icon: StandardIcon.Critical
|
||||||
|
standardButtons: StandardButton.Ok
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,8 +6,8 @@ import Session 1.0
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
property Session session
|
property Session session
|
||||||
property string appname
|
property string appName
|
||||||
property string stageText : "Starting " + appname + "..."
|
property string stageText : "Starting " + appName + "..."
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
|||||||
@@ -6,5 +6,6 @@
|
|||||||
<file>gui/SettingsView.qml</file>
|
<file>gui/SettingsView.qml</file>
|
||||||
<file>gui/StreamSegue.qml</file>
|
<file>gui/StreamSegue.qml</file>
|
||||||
<file>gui/GamepadMapper.qml</file>
|
<file>gui/GamepadMapper.qml</file>
|
||||||
|
<file>gui/QuitSegue.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
Reference in New Issue
Block a user