2018-07-08 05:15:02 +00:00
import QtQuick 2.9
2018-07-08 17:19:08 +00:00
import QtQuick . Controls 2.2
2020-11-24 06:13:39 +00:00
import QtQuick . Layouts 1.2
2018-07-08 17:19:08 +00:00
2018-07-09 05:56:38 +00:00
import StreamingPreferences 1.0
2018-09-09 19:33:19 +00:00
import ComputerManager 1.0
2018-09-30 20:41:32 +00:00
import SdlGamepadKeyNavigation 1.0
2019-03-23 19:05:08 +00:00
import SystemProperties 1.0
2018-07-09 05:56:38 +00:00
2018-11-14 02:03:53 +00:00
Flickable {
2018-07-08 05:15:02 +00:00
id: settingsPage
2020-11-21 17:42:16 +00:00
objectName: qsTr ( "Settings" )
2018-11-14 02:03:53 +00:00
2020-02-20 21:38:01 +00:00
boundsBehavior: Flickable . OvershootBounds
2018-11-14 02:03:53 +00:00
contentWidth: settingsColumn1 . width > settingsColumn2 . width ? settingsColumn1.width : settingsColumn2 . width
contentHeight: settingsColumn1 . height > settingsColumn2 . height ? settingsColumn1.height : settingsColumn2 . height
ScrollBar.vertical: ScrollBar {
anchors {
2020-05-10 19:53:27 +00:00
left: parent . right
2018-11-14 02:03:53 +00:00
leftMargin: - 10
}
}
2018-07-08 05:15:02 +00:00
2019-02-23 06:14:06 +00:00
StackView.onActivated: {
2019-05-19 17:16:54 +00:00
// This enables Tab and BackTab based navigation rather than arrow keys.
// It is required to shift focus between controls on the settings page.
SdlGamepadKeyNavigation . setUiNavMode ( true )
2019-05-19 18:08:23 +00:00
// Highlight the first item if a gamepad is connected
if ( SdlGamepadKeyNavigation . getConnectedGamepads ( ) > 0 ) {
resolutionComboBox . forceActiveFocus ( Qt . TabFocus )
}
2018-09-30 20:41:32 +00:00
}
2019-02-23 06:14:06 +00:00
StackView.onDeactivating: {
2019-05-19 17:16:54 +00:00
SdlGamepadKeyNavigation . setUiNavMode ( false )
2019-03-28 01:13:20 +00:00
// Save the prefs so the Session can observe the changes
StreamingPreferences . save ( )
2018-07-09 05:56:38 +00:00
}
2018-07-08 17:19:08 +00:00
Column {
2018-07-20 22:47:50 +00:00
padding: 10
id: settingsColumn1
2020-05-10 19:30:15 +00:00
width: settingsPage . width / 2
spacing: 15
2018-07-08 17:19:08 +00:00
GroupBox {
2018-07-08 18:12:22 +00:00
id: basicSettingsGroupBox
2020-05-10 20:02:10 +00:00
width: ( parent . width - ( parent . leftPadding + parent . rightPadding ) )
2018-07-08 17:19:08 +00:00
padding: 12
2020-11-21 19:15:54 +00:00
title: "<font color=\"skyblue\">" + qsTr ( "Basic Settings" ) + "</font>"
2018-07-08 18:12:22 +00:00
font.pointSize: 12
2018-07-08 17:19:08 +00:00
Column {
anchors.fill: parent
spacing: 5
Label {
width: parent . width
id: resFPStitle
2018-07-28 08:22:31 +00:00
text: qsTr ( "Resolution and FPS" )
2018-07-08 17:19:08 +00:00
font.pointSize: 12
2018-11-22 10:35:25 +00:00
wrapMode: Text . Wrap
2018-07-08 17:19:08 +00:00
}
Label {
width: parent . width
id: resFPSdesc
2018-11-04 22:36:12 +00:00
text: qsTr ( "Setting values too high for your PC or network connection may cause lag, stuttering, or errors." )
2018-07-08 17:19:08 +00:00
font.pointSize: 9
wrapMode: Text . Wrap
}
2018-07-28 08:22:31 +00:00
Row {
spacing: 5
2020-05-10 18:12:37 +00:00
width: parent . width
2018-07-28 08:22:31 +00:00
2018-10-06 19:12:05 +00:00
AutoResizingComboBox {
2020-11-24 06:13:39 +00:00
property int lastIndexValue
2018-07-28 08:22:31 +00:00
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
2018-08-05 21:55:26 +00:00
// Add native resolutions for all attached displays
2018-09-04 04:21:37 +00:00
var done = false
for ( var displayIndex = 0 ; ! done ; displayIndex ++ ) {
for ( var displayResIndex = 0 ; displayResIndex < 2 ; displayResIndex ++ ) {
var screenRect ;
2018-08-05 21:55:26 +00:00
2018-09-04 04:21:37 +00:00
// Some platforms have different desktop resolutions
// and native resolutions (like macOS with Retina displays)
2020-02-09 05:31:04 +00:00
if ( displayResIndex === 0 ) {
2019-03-23 19:05:08 +00:00
screenRect = SystemProperties . getDesktopResolution ( displayIndex )
2018-09-04 04:21:37 +00:00
}
else {
2019-03-23 19:05:08 +00:00
screenRect = SystemProperties . getNativeResolution ( displayIndex )
2018-09-04 04:21:37 +00:00
}
2018-08-05 21:55:26 +00:00
2018-09-04 04:21:37 +00:00
if ( screenRect . width === 0 ) {
// Exceeded max count of displays
done = true
2018-08-05 21:55:26 +00:00
break
}
2018-09-04 04:21:37 +00:00
var indexToAdd = 0
for ( var j = 0 ; j < resolutionComboBox . count ; j ++ ) {
var existing_width = parseInt ( resolutionListModel . get ( j ) . video_width ) ;
var existing_height = parseInt ( resolutionListModel . get ( j ) . video_height ) ;
if ( screenRect . width === existing_width && screenRect . height === existing_height ) {
// Duplicate entry, skip
indexToAdd = - 1
break
}
else if ( screenRect . width * screenRect . height > existing_width * existing_height ) {
// Candidate entrypoint after this entry
indexToAdd = j + 1
}
2018-08-05 21:55:26 +00:00
}
2018-09-04 04:21:37 +00:00
// Insert this display's resolution if it's not a duplicate
if ( indexToAdd >= 0 ) {
resolutionListModel . insert ( indexToAdd ,
{
"text" : "Native (" + screenRect . width + "x" + screenRect . height + ")" ,
"video_width" : "" + screenRect . width ,
2020-11-24 06:13:39 +00:00
"video_height" : "" + screenRect . height ,
"is_custom" : false
2018-09-04 04:21:37 +00:00
} )
}
2018-08-05 21:55:26 +00:00
}
}
2020-02-23 08:43:43 +00:00
// Prune resolutions that are over the decoder's maximum
var max_pixels = SystemProperties . maximumResolution . width * SystemProperties . maximumResolution . height ;
if ( max_pixels > 0 ) {
for ( var j = 0 ; j < resolutionComboBox . count ; j ++ ) {
var existing_width = parseInt ( resolutionListModel . get ( j ) . video_width ) ;
var existing_height = parseInt ( resolutionListModel . get ( j ) . video_height ) ;
if ( existing_width * existing_height > max_pixels ) {
resolutionListModel . remove ( j )
j --
}
}
}
2018-07-28 08:22:31 +00:00
// load the saved width/height, and iterate through the ComboBox until a match is found
// and set it to that index.
2019-03-28 01:13:20 +00:00
var saved_width = StreamingPreferences . width
var saved_height = StreamingPreferences . height
2020-11-24 06:13:39 +00:00
var index_set = false
2018-09-08 21:33:34 +00:00
for ( var i = 0 ; i < resolutionListModel . count ; i ++ ) {
2018-07-28 08:22:31 +00:00
var el_width = parseInt ( resolutionListModel . get ( i ) . video_width ) ;
var el_height = parseInt ( resolutionListModel . get ( i ) . video_height ) ;
2018-08-05 21:55:26 +00:00
2020-11-24 06:13:39 +00:00
if ( saved_width === el_width && saved_height === el_height ) {
2018-07-28 08:22:31 +00:00
currentIndex = i
2020-11-24 06:13:39 +00:00
index_set = true
break
2018-07-28 08:22:31 +00:00
}
}
2018-09-08 06:16:13 +00:00
2020-11-24 06:13:39 +00:00
if ( ! index_set ) {
// We did not find a match. This must be a custom resolution.
resolutionListModel . append ( {
"text" : "Custom (" + StreamingPreferences . width + "x" + StreamingPreferences . height + ")" ,
"video_width" : "" + StreamingPreferences . width ,
"video_height" : "" + StreamingPreferences . height ,
"is_custom" : true
} )
currentIndex = resolutionListModel . count - 1
}
else {
resolutionListModel . append ( {
"text" : "Custom" ,
"video_width" : "" ,
"video_height" : "" ,
"is_custom" : true
} )
}
// Since we don't call activate() here, we need to trigger
// width calculation manually
recalculateWidth ( )
lastIndexValue = currentIndex
2018-07-16 01:27:41 +00:00
}
2018-07-28 08:22:31 +00:00
id: resolutionComboBox
2020-05-10 18:12:37 +00:00
maximumWidth: parent . width / 2
2018-07-28 08:22:31 +00:00
textRole: "text"
model: ListModel {
id: resolutionListModel
2018-08-05 21:55:26 +00:00
// Other elements may be added at runtime
// based on attached display resolution
2018-07-28 08:22:31 +00:00
ListElement {
2020-11-21 19:15:54 +00:00
text: qsTr ( "720p" )
2018-07-28 08:22:31 +00:00
video_width: "1280"
video_height: "720"
2020-11-24 06:13:39 +00:00
is_custom: false
2018-07-28 08:22:31 +00:00
}
ListElement {
2020-11-21 19:15:54 +00:00
text: qsTr ( "1080p" )
2018-07-28 08:22:31 +00:00
video_width: "1920"
video_height: "1080"
2020-11-24 06:13:39 +00:00
is_custom: false
2018-07-28 08:22:31 +00:00
}
ListElement {
2020-11-21 19:15:54 +00:00
text: qsTr ( "1440p" )
2018-07-28 08:22:31 +00:00
video_width: "2560"
video_height: "1440"
2020-11-24 06:13:39 +00:00
is_custom: false
2018-07-28 08:22:31 +00:00
}
ListElement {
2020-11-21 19:15:54 +00:00
text: qsTr ( "4K" )
2018-07-28 08:22:31 +00:00
video_width: "3840"
video_height: "2160"
2020-11-24 06:13:39 +00:00
is_custom: false
2018-07-28 08:22:31 +00:00
}
2018-07-16 01:27:41 +00:00
}
2020-11-24 06:13:39 +00:00
function updateBitrateForSelection ( ) {
2018-09-08 06:16:13 +00:00
var selectedWidth = parseInt ( resolutionListModel . get ( currentIndex ) . video_width )
var selectedHeight = parseInt ( resolutionListModel . get ( currentIndex ) . video_height )
// Only modify the bitrate if the values actually changed
2019-03-28 01:13:20 +00:00
if ( StreamingPreferences . width !== selectedWidth || StreamingPreferences . height !== selectedHeight ) {
StreamingPreferences . width = selectedWidth
StreamingPreferences . height = selectedHeight
StreamingPreferences . bitrateKbps = StreamingPreferences . getDefaultBitrate ( StreamingPreferences . width ,
StreamingPreferences . height ,
StreamingPreferences . fps ) ;
slider . value = StreamingPreferences . bitrateKbps
2018-09-08 06:16:13 +00:00
}
2020-11-24 06:13:39 +00:00
lastIndexValue = currentIndex
}
// ::onActivated must be used, as it only listens for when the index is changed by a human
onActivated : {
if ( resolutionListModel . get ( currentIndex ) . is_custom ) {
customResolutionDialog . open ( )
}
else {
updateBitrateForSelection ( )
}
}
NavigableDialog {
id: customResolutionDialog
standardButtons: Dialog . Ok | Dialog . Cancel
onOpened: {
// Force keyboard focus on the textbox so keyboard navigation works
widthField . forceActiveFocus ( )
// standardButton() was added in Qt 5.10, so we must check for it first
if ( customResolutionDialog . standardButton ) {
customResolutionDialog . standardButton ( Dialog . Ok ) . enabled = customResolutionDialog . isInputValid ( )
}
}
onClosed: {
widthField . clear ( )
heightField . clear ( )
}
onRejected: {
resolutionComboBox . currentIndex = resolutionComboBox . lastIndexValue
}
function isInputValid ( ) {
// If we have text in either textbox that isn't valid,
// reject the input.
if ( ( ! widthField . acceptableInput && widthField . text ) ||
( ! heightField . acceptableInput && heightField . text ) ) {
return false
}
// The textboxes need to have text or placeholder text
if ( ( ! widthField . text && ! widthField . placeholderText ) ||
( ! heightField . text && ! heightField . placeholderText ) ) {
return false
}
return true
}
onAccepted: {
// Reject if there's invalid input
if ( ! isInputValid ( ) ) {
reject ( )
return
}
var width = widthField . text ? widthField.text : widthField . placeholderText
var height = heightField . text ? heightField.text : heightField . placeholderText
// Find and update the custom entry
for ( var i = 0 ; i < resolutionListModel . count ; i ++ ) {
if ( resolutionListModel . get ( i ) . is_custom ) {
resolutionListModel . setProperty ( i , "video_width" , width )
resolutionListModel . setProperty ( i , "video_height" , height )
resolutionListModel . setProperty ( i , "text" , "Custom (" + width + "x" + height + ")" )
// Now update the bitrate using the custom resolution
resolutionComboBox . currentIndex = i
resolutionComboBox . updateBitrateForSelection ( )
// Update the combobox width too
resolutionComboBox . recalculateWidth ( )
break
}
}
}
ColumnLayout {
Label {
text: qsTr ( "Custom resolutions are not officially supported by GeForce Experience, so it will not set your host display resolution. You will need to set it manually while in game." ) + "\n\n" +
qsTr ( "Resolutions that are not supported by your client or host PC may cause streaming errors." ) + "\n"
wrapMode: Label . WordWrap
Layout.maximumWidth: 300
}
Label {
text: qsTr ( "Enter a custom resolution:" )
font.bold: true
}
RowLayout {
TextField {
id: widthField
maximumLength: 5
inputMethodHints: Qt . ImhDigitsOnly
placeholderText: resolutionListModel . get ( resolutionComboBox . currentIndex ) . video_width
validator: IntValidator { bottom: 128 ; top: 8192 }
focus: true
onTextChanged: {
// standardButton() was added in Qt 5.10, so we must check for it first
if ( customResolutionDialog . standardButton ) {
customResolutionDialog . standardButton ( Dialog . Ok ) . enabled = customResolutionDialog . isInputValid ( )
}
}
Keys.onReturnPressed: {
customResolutionDialog . accept ( )
}
}
Label {
text: "x"
font.bold: true
}
TextField {
id: heightField
maximumLength: 5
inputMethodHints: Qt . ImhDigitsOnly
placeholderText: resolutionListModel . get ( resolutionComboBox . currentIndex ) . video_height
validator: IntValidator { bottom: 128 ; top: 8192 }
onTextChanged: {
// standardButton() was added in Qt 5.10, so we must check for it first
if ( customResolutionDialog . standardButton ) {
customResolutionDialog . standardButton ( Dialog . Ok ) . enabled = customResolutionDialog . isInputValid ( )
}
}
Keys.onReturnPressed: {
customResolutionDialog . accept ( )
}
}
}
}
2018-07-16 01:27:41 +00:00
}
2018-07-28 08:22:31 +00:00
}
2018-10-06 19:12:05 +00:00
AutoResizingComboBox {
2018-09-08 21:33:34 +00:00
function createModel ( ) {
var fpsListModel = Qt . createQmlObject ( 'import QtQuick 2.0; ListModel {}' , parent , '' )
2019-03-24 03:25:19 +00:00
var max_fps = SystemProperties . maximumStreamingFrameRate
2018-09-08 21:33:34 +00:00
// Default entries
2020-11-21 19:15:54 +00:00
fpsListModel . append ( { "text" : qsTr ( "%1 FPS" ) . arg ( "30" ) , "video_fps" : "30" } )
fpsListModel . append ( { "text" : qsTr ( "%1 FPS" ) . arg ( "60" ) , "video_fps" : "60" } )
2018-09-08 21:33:34 +00:00
2018-09-08 22:09:46 +00:00
// Add unsupported FPS values that come before the display max FPS
2019-03-28 01:13:20 +00:00
if ( StreamingPreferences . unsupportedFps ) {
2019-03-24 03:25:19 +00:00
if ( max_fps > 90 ) {
2020-11-21 19:15:54 +00:00
fpsListModel . append ( { "text" : qsTr ( "%1 FPS (Unsupported)" ) . arg ( "90" ) , "video_fps" : "90" } )
2018-09-08 22:09:46 +00:00
}
2019-03-24 03:25:19 +00:00
if ( max_fps > 120 ) {
2020-11-21 19:15:54 +00:00
fpsListModel . append ( { "text" : qsTr ( "%1 FPS (Unsupported)" ) . arg ( "120" ) , "video_fps" : "120" } )
2018-09-08 22:09:46 +00:00
}
}
2018-07-28 08:22:31 +00:00
// Use 64 as the cutoff for adding a separate option to
// handle wonky displays that report just over 60 Hz.
2019-03-24 03:25:19 +00:00
if ( max_fps > 64 ) {
2018-11-21 05:47:08 +00:00
// Mark any FPS value greater than 120 as unsupported
2019-03-28 01:13:20 +00:00
if ( StreamingPreferences . unsupportedFps && max_fps > 120 ) {
2020-11-21 19:15:54 +00:00
fpsListModel . append ( { "text" : qsTr ( "%1 FPS (Unsupported)" ) . arg ( max_fps ) , "video_fps" : "" + max_fps } )
2018-11-21 05:47:08 +00:00
}
2019-03-24 03:25:19 +00:00
else if ( max_fps > 120 ) {
2020-11-21 19:15:54 +00:00
fpsListModel . append ( { "text" : qsTr ( "%1 FPS" ) . arg ( "120" ) , "video_fps" : "120" } )
2018-11-21 05:47:08 +00:00
}
else {
2020-11-21 19:15:54 +00:00
fpsListModel . append ( { "text" : qsTr ( "%1 FPS" ) . arg ( max_fps ) , "video_fps" : "" + max_fps } )
2018-11-21 05:47:08 +00:00
}
2018-07-28 08:22:31 +00:00
}
2018-09-08 22:09:46 +00:00
// Add unsupported FPS values that come after the display max FPS
2019-03-28 01:13:20 +00:00
if ( StreamingPreferences . unsupportedFps ) {
2019-03-24 03:25:19 +00:00
if ( max_fps < 90 ) {
2020-11-21 19:15:54 +00:00
fpsListModel . append ( { "text" : qsTr ( "%1 FPS (Unsupported)" ) . arg ( "90" ) , "video_fps" : "90" } )
2018-09-08 21:33:34 +00:00
}
2019-03-24 03:25:19 +00:00
if ( max_fps < 120 ) {
2020-11-21 19:15:54 +00:00
fpsListModel . append ( { "text" : qsTr ( "%1 FPS (Unsupported)" ) . arg ( "120" ) , "video_fps" : "120" } )
2018-09-08 21:33:34 +00:00
}
}
return fpsListModel
}
function reinitialize ( ) {
model = createModel ( )
2019-03-28 01:13:20 +00:00
var saved_fps = StreamingPreferences . fps
2018-07-28 08:22:31 +00:00
currentIndex = 0
2018-09-08 21:33:34 +00:00
for ( var i = 0 ; i < model . count ; i ++ ) {
var el_fps = parseInt ( model . get ( i ) . video_fps ) ;
2018-08-05 21:55:26 +00:00
// Pick the highest value lesser or equal to the saved FPS
2018-08-05 22:09:36 +00:00
if ( saved_fps >= el_fps ) {
2018-07-28 08:22:31 +00:00
currentIndex = i
}
}
2018-09-08 06:16:13 +00:00
// Persist the selected value
activated ( currentIndex )
2018-07-16 01:27:41 +00:00
}
2018-07-28 08:22:31 +00:00
2018-09-08 21:33:34 +00:00
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
reinitialize ( )
}
2018-07-28 08:22:31 +00:00
id: fpsComboBox
2020-05-10 18:12:37 +00:00
maximumWidth: parent . width / 2
2018-07-28 08:22:31 +00:00
textRole: "text"
// ::onActivated must be used, as it only listens for when the index is changed by a human
onActivated : {
2018-09-08 21:33:34 +00:00
var selectedFps = parseInt ( model . get ( currentIndex ) . video_fps )
2018-09-08 06:16:13 +00:00
// Only modify the bitrate if the values actually changed
2019-03-28 01:13:20 +00:00
if ( StreamingPreferences . fps !== selectedFps ) {
StreamingPreferences . fps = selectedFps
2018-07-28 08:22:31 +00:00
2019-03-28 01:13:20 +00:00
StreamingPreferences . bitrateKbps = StreamingPreferences . getDefaultBitrate ( StreamingPreferences . width ,
StreamingPreferences . height ,
StreamingPreferences . fps ) ;
slider . value = StreamingPreferences . bitrateKbps
2018-09-08 06:16:13 +00:00
}
2018-07-16 01:27:41 +00:00
}
}
2018-07-08 17:19:08 +00:00
}
Label {
width: parent . width
id: bitrateTitle
2020-11-21 19:15:54 +00:00
text: qsTr ( "Video bitrate:" )
2018-07-08 17:19:08 +00:00
font.pointSize: 12
wrapMode: Text . Wrap
}
Label {
width: parent . width
id: bitrateDesc
2018-12-25 19:48:34 +00:00
text: qsTr ( "Lower the bitrate on slower connections. Raise the bitrate to increase image quality." )
2018-07-08 17:19:08 +00:00
font.pointSize: 9
wrapMode: Text . Wrap
}
Slider {
id: slider
2019-03-28 01:13:20 +00:00
value: StreamingPreferences . bitrateKbps
2018-07-18 01:52:06 +00:00
2018-07-08 17:19:08 +00:00
stepSize: 500
from : 500
2018-07-28 08:22:31 +00:00
to: 150000
2018-07-18 01:52:06 +00:00
2018-07-08 17:19:08 +00:00
snapMode: "SnapOnRelease"
width: Math . min ( bitrateDesc . implicitWidth , parent . width )
2018-07-09 05:56:38 +00:00
onValueChanged: {
2020-11-21 19:15:54 +00:00
bitrateTitle . text = qsTr ( "Video bitrate: %1 Mbps" ) . arg ( value / 1000.0 )
2019-03-28 01:13:20 +00:00
StreamingPreferences . bitrateKbps = value
2018-07-08 17:19:08 +00:00
}
}
2018-07-08 18:12:22 +00:00
2018-09-04 02:17:34 +00:00
Label {
width: parent . width
id: windowModeTitle
text: qsTr ( "Display mode" )
font.pointSize: 12
wrapMode: Text . Wrap
}
2018-10-06 19:12:05 +00:00
AutoResizingComboBox {
2018-09-04 02:17:34 +00:00
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
2019-06-29 21:58:27 +00:00
// Set the recommended option based on the OS
for ( var i = 0 ; i < windowModeListModel . count ; i ++ ) {
var thisWm = windowModeListModel . get ( i ) . val ;
if ( thisWm === StreamingPreferences . recommendedFullScreenMode ) {
2020-11-21 17:42:16 +00:00
windowModeListModel . get ( i ) . text += qsTr ( " (Recommended)" )
2019-06-29 21:58:27 +00:00
windowModeListModel . move ( i , 0 , 1 ) ;
break
}
}
2018-09-04 02:17:34 +00:00
currentIndex = 0
2020-02-09 05:31:04 +00:00
2020-02-09 19:35:05 +00:00
if ( SystemProperties . hasWindowManager && ! SystemProperties . rendererAlwaysFullScreen ) {
2020-02-09 05:31:04 +00:00
var savedWm = StreamingPreferences . windowMode
for ( var i = 0 ; i < windowModeListModel . count ; i ++ ) {
var thisWm = windowModeListModel . get ( i ) . val ;
if ( savedWm === thisWm ) {
currentIndex = i
break
}
}
2018-08-21 05:25:19 +00:00
}
2020-02-09 05:31:04 +00:00
2018-09-08 06:16:13 +00:00
activated ( currentIndex )
2018-08-21 05:25:19 +00:00
}
2018-09-04 02:17:34 +00:00
id: windowModeComboBox
2020-02-09 19:35:05 +00:00
enabled: SystemProperties . hasWindowManager && ! SystemProperties . rendererAlwaysFullScreen
2018-11-04 22:36:12 +00:00
hoverEnabled: true
2018-09-04 02:17:34 +00:00
textRole: "text"
model: ListModel {
id: windowModeListModel
ListElement {
2020-11-21 17:42:16 +00:00
text: qsTr ( "Full-screen" )
2018-09-04 02:17:34 +00:00
val: StreamingPreferences . WM_FULLSCREEN
}
ListElement {
2020-11-21 17:42:16 +00:00
text: qsTr ( "Borderless windowed" )
2018-09-04 02:17:34 +00:00
val: StreamingPreferences . WM_FULLSCREEN_DESKTOP
}
ListElement {
2020-11-21 17:42:16 +00:00
text: qsTr ( "Windowed" )
2018-09-04 02:17:34 +00:00
val: StreamingPreferences . WM_WINDOWED
2018-08-21 05:25:19 +00:00
}
2018-07-09 05:56:38 +00:00
}
2018-09-04 02:17:34 +00:00
onActivated: {
2019-03-28 01:13:20 +00:00
StreamingPreferences . windowMode = windowModeListModel . get ( currentIndex ) . val
2018-09-04 02:17:34 +00:00
}
2018-11-04 22:36:12 +00:00
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
2020-11-21 17:42:16 +00:00
ToolTip.text: qsTr ( "Full-screen generally provides the best performance, but borderless windowed may work better with features like macOS Spaces, Alt+Tab, screenshot tools, on-screen overlays, etc." )
2018-09-04 02:17:34 +00:00
}
CheckBox {
id: vsyncCheck
2020-05-10 18:12:37 +00:00
width: parent . width
2018-11-04 22:36:12 +00:00
hoverEnabled: true
2020-11-21 19:15:54 +00:00
text: qsTr ( "V-Sync" )
2018-09-04 02:17:34 +00:00
font.pointSize: 12
2019-03-28 01:13:20 +00:00
checked: StreamingPreferences . enableVsync
2018-09-04 02:17:34 +00:00
onCheckedChanged: {
2019-03-28 01:13:20 +00:00
StreamingPreferences . enableVsync = checked
2018-09-04 02:17:34 +00:00
}
2018-11-04 22:36:12 +00:00
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
2020-11-21 17:42:16 +00:00
ToolTip.text: qsTr ( "Disabling V-Sync allows sub-frame rendering latency, but it can display visible tearing" )
2018-07-08 18:12:22 +00:00
}
2018-12-25 20:57:00 +00:00
CheckBox {
id: framePacingCheck
2020-05-10 18:12:37 +00:00
width: parent . width
2018-12-25 20:57:00 +00:00
hoverEnabled: true
2020-11-21 17:42:16 +00:00
text: qsTr ( "Frame pacing" )
2018-12-25 20:57:00 +00:00
font.pointSize: 12
2019-03-28 01:13:20 +00:00
enabled: StreamingPreferences . enableVsync
checked: StreamingPreferences . enableVsync && StreamingPreferences . framePacing
2018-12-25 20:57:00 +00:00
onCheckedChanged: {
2019-03-28 01:13:20 +00:00
StreamingPreferences . framePacing = checked
2018-12-25 20:57:00 +00:00
}
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
2020-11-21 17:42:16 +00:00
ToolTip.text: qsTr ( "Frame pacing reduces micro-stutter by delaying frames that come in too early" )
2018-12-25 20:57:00 +00:00
}
2018-07-08 18:12:22 +00:00
}
}
GroupBox {
2018-07-18 02:39:16 +00:00
2018-07-08 18:12:22 +00:00
id: audioSettingsGroupBox
2020-05-10 20:02:10 +00:00
width: ( parent . width - ( parent . leftPadding + parent . rightPadding ) )
2018-07-08 18:12:22 +00:00
padding: 12
2020-11-21 19:15:54 +00:00
title: "<font color=\"skyblue\">" + qsTr ( "Audio Settings" ) + "</font>"
2018-07-08 18:12:22 +00:00
font.pointSize: 12
Column {
anchors.fill: parent
spacing: 5
2018-07-20 21:35:47 +00:00
Label {
width: parent . width
id: resAudioTitle
text: qsTr ( "Audio configuration" )
font.pointSize: 12
wrapMode: Text . Wrap
}
2018-07-18 02:39:16 +00:00
2018-10-06 19:12:05 +00:00
AutoResizingComboBox {
2018-07-20 21:35:47 +00:00
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
2019-03-28 01:13:20 +00:00
var saved_audio = StreamingPreferences . audioConfig
2018-07-20 21:35:47 +00:00
currentIndex = 0
2018-09-08 06:16:13 +00:00
for ( var i = 0 ; i < audioListModel . count ; i ++ ) {
var el_audio = audioListModel . get ( i ) . val ;
if ( saved_audio === el_audio ) {
currentIndex = i
break
}
2018-07-20 21:35:47 +00:00
}
2018-09-08 06:16:13 +00:00
activated ( currentIndex )
2018-07-20 21:35:47 +00:00
}
2018-07-18 02:39:16 +00:00
2018-07-20 21:35:47 +00:00
id: audioComboBox
textRole: "text"
model: ListModel {
id: audioListModel
ListElement {
2020-11-21 19:15:54 +00:00
text: qsTr ( "Stereo" )
2018-10-02 22:30:22 +00:00
val: StreamingPreferences . AC_STEREO
2018-07-20 21:35:47 +00:00
}
ListElement {
2020-11-21 19:15:54 +00:00
text: qsTr ( "5.1 surround sound" )
2018-10-02 22:30:22 +00:00
val: StreamingPreferences . AC_51_SURROUND
2018-07-20 21:35:47 +00:00
}
2020-04-03 07:12:52 +00:00
ListElement {
2020-11-21 19:15:54 +00:00
text: qsTr ( "7.1 surround sound" )
2020-04-03 07:12:52 +00:00
val: StreamingPreferences . AC_71_SURROUND
}
2018-07-20 21:35:47 +00:00
}
// ::onActivated must be used, as it only listens for when the index is changed by a human
onActivated : {
2019-03-28 01:13:20 +00:00
StreamingPreferences . audioConfig = audioListModel . get ( currentIndex ) . val
2018-07-18 02:39:16 +00:00
}
2018-07-08 18:12:22 +00:00
}
2018-07-20 21:35:47 +00:00
2018-07-08 18:12:22 +00:00
}
}
2018-11-16 00:41:02 +00:00
GroupBox {
id: uiSettingsGroupBox
2020-05-10 20:02:10 +00:00
width: ( parent . width - ( parent . leftPadding + parent . rightPadding ) )
2018-11-16 00:41:02 +00:00
padding: 12
2020-11-21 19:15:54 +00:00
title: "<font color=\"skyblue\">" + qsTr ( "UI Settings" ) + "</font>"
2018-11-16 00:41:02 +00:00
font.pointSize: 12
Column {
anchors.fill: parent
spacing: 5
CheckBox {
2018-11-29 05:46:14 +00:00
id: startMaximizedCheck
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Maximize Moonlight window on startup" )
2018-11-16 00:41:02 +00:00
font.pointSize: 12
2020-02-09 05:31:04 +00:00
enabled: SystemProperties . hasWindowManager
checked: ! StreamingPreferences . startWindowed || ! SystemProperties . hasWindowManager
2018-11-16 00:41:02 +00:00
onCheckedChanged: {
2019-03-28 01:13:20 +00:00
StreamingPreferences . startWindowed = ! checked
2018-11-16 00:41:02 +00:00
}
}
2019-03-19 03:21:52 +00:00
CheckBox {
id: connectionWarningsCheck
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Show connection quality warnings" )
2019-03-19 03:21:52 +00:00
font.pointSize: 12
2019-03-28 01:13:20 +00:00
checked: StreamingPreferences . connectionWarnings
2019-03-19 03:21:52 +00:00
onCheckedChanged: {
2019-03-28 01:13:20 +00:00
StreamingPreferences . connectionWarnings = checked
2019-03-19 03:21:52 +00:00
}
}
2019-06-30 00:40:30 +00:00
CheckBox {
visible: SystemProperties . hasDiscordIntegration
id: discordPresenceCheck
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Discord Rich Presence integration" )
2019-06-30 00:40:30 +00:00
font.pointSize: 12
checked: StreamingPreferences . richPresence
onCheckedChanged: {
StreamingPreferences . richPresence = checked
}
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
2020-11-21 17:42:16 +00:00
ToolTip.text: qsTr ( "Updates your Discord status to display the name of the game you're streaming." )
2019-06-30 00:40:30 +00:00
}
2018-11-16 00:41:02 +00:00
}
}
2018-07-20 22:47:50 +00:00
}
Column {
padding: 10
2020-05-10 20:02:10 +00:00
rightPadding: 20
2018-07-20 22:47:50 +00:00
anchors.left: settingsColumn1 . right
id: settingsColumn2
2020-05-10 19:30:15 +00:00
width: settingsPage . width / 2
spacing: 15
2018-07-08 18:12:22 +00:00
GroupBox {
id: gamepadSettingsGroupBox
2020-05-10 20:02:10 +00:00
width: ( parent . width - ( parent . leftPadding + parent . rightPadding ) )
2018-07-08 18:12:22 +00:00
padding: 12
2020-11-21 19:15:54 +00:00
title: "<font color=\"skyblue\">" + qsTr ( "Input Settings" ) + "</font>"
2018-07-08 18:12:22 +00:00
font.pointSize: 12
2018-11-16 00:41:02 +00:00
Column {
2018-07-08 18:12:22 +00:00
anchors.fill: parent
spacing: 5
CheckBox {
2018-11-30 04:10:47 +00:00
id: singleControllerCheck
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Force gamepad #1 always present" )
2018-07-08 18:12:22 +00:00
font.pointSize: 12
2019-03-28 01:13:20 +00:00
checked: ! StreamingPreferences . multiController
2018-07-09 05:56:38 +00:00
onCheckedChanged: {
2019-03-28 01:13:20 +00:00
StreamingPreferences . multiController = ! checked
2018-07-09 05:56:38 +00:00
}
2018-11-30 04:10:47 +00:00
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
2020-11-21 19:15:54 +00:00
ToolTip.text: qsTr ( "Forces a single gamepad to always stay connected to the host, even if no gamepads are actually connected to this PC." ) + "\n" +
2020-11-21 17:42:16 +00:00
qsTr ( "Only enable this option when streaming a game that doesn't support gamepads being connected after startup." )
2018-07-08 18:12:22 +00:00
}
2018-09-09 20:21:11 +00:00
CheckBox {
2020-04-25 20:00:39 +00:00
id: absoluteMouseCheck
2018-11-04 21:31:28 +00:00
hoverEnabled: true
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Optimize mouse for remote desktop instead of games" )
2018-09-09 20:21:11 +00:00
font.pointSize: 12
2020-04-25 20:04:22 +00:00
enabled: SystemProperties . hasWindowManager
checked: StreamingPreferences . absoluteMouseMode && SystemProperties . hasWindowManager
2018-09-09 20:21:11 +00:00
onCheckedChanged: {
2020-04-25 20:00:39 +00:00
StreamingPreferences . absoluteMouseMode = checked
2018-09-09 20:21:11 +00:00
}
2018-11-04 21:31:28 +00:00
ToolTip.delay: 1000
2020-04-25 20:00:39 +00:00
ToolTip.timeout: 5000
2018-11-04 21:31:28 +00:00
ToolTip.visible: hovered
2020-11-21 19:15:54 +00:00
ToolTip.text: qsTr ( "This enables mouse control without capturing the client's mouse cursor. It will not work in most games." ) + "\n" +
qsTr ( "You can toggle this while streaming using Ctrl+Alt+Shift+M." )
2018-09-09 20:21:11 +00:00
}
2019-06-30 01:24:59 +00:00
2020-05-01 03:55:15 +00:00
CheckBox {
id: absoluteTouchCheck
hoverEnabled: true
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Use touchscreen as a trackpad" )
2020-05-01 03:55:15 +00:00
font.pointSize: 12
checked: ! StreamingPreferences . absoluteTouchMode
onCheckedChanged: {
StreamingPreferences . absoluteTouchMode = ! checked
}
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
2020-11-21 17:42:16 +00:00
ToolTip.text: qsTr ( "When checked, the touchscreen acts like a trackpad. When unchecked, the touchscreen will directly control the mouse pointer." )
2020-05-01 03:55:15 +00:00
}
2019-06-30 01:24:59 +00:00
CheckBox {
id: gamepadMouseCheck
hoverEnabled: true
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Gamepad mouse mode support" )
2019-06-30 01:24:59 +00:00
font.pointSize: 12
checked: StreamingPreferences . gamepadMouse
onCheckedChanged: {
StreamingPreferences . gamepadMouse = checked
}
ToolTip.delay: 1000
ToolTip.timeout: 3000
ToolTip.visible: hovered
2020-11-21 17:42:16 +00:00
ToolTip.text: qsTr ( "When enabled, holding the Start button will toggle mouse mode" )
2019-06-30 01:24:59 +00:00
}
2020-08-23 14:05:00 +00:00
CheckBox {
id: swapMouseButtonsCheck
hoverEnabled: true
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Swap mouse buttons" )
2020-08-23 14:05:00 +00:00
font.pointSize: 12
checked: StreamingPreferences . swapMouseButtons
onCheckedChanged: {
StreamingPreferences . swapMouseButtons = checked
}
ToolTip.delay: 1000
ToolTip.timeout: 3000
ToolTip.visible: hovered
2020-11-21 17:42:16 +00:00
ToolTip.text: qsTr ( "When checked, swap the left and right mouse buttons" )
2020-08-23 14:05:00 +00:00
}
2018-07-08 18:12:22 +00:00
}
}
GroupBox {
id: hostSettingsGroupBox
2020-05-10 20:02:10 +00:00
width: ( parent . width - ( parent . leftPadding + parent . rightPadding ) )
2018-07-08 18:12:22 +00:00
padding: 12
2020-11-21 19:15:54 +00:00
title: "<font color=\"skyblue\">" + qsTr ( "Host Settings" ) + "</font>"
2018-07-08 18:12:22 +00:00
font.pointSize: 12
2018-11-16 00:41:02 +00:00
Column {
2018-07-08 18:12:22 +00:00
anchors.fill: parent
spacing: 5
CheckBox {
id: optimizeGameSettingsCheck
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Optimize game settings for streaming" )
2018-07-08 18:12:22 +00:00
font.pointSize: 12
2019-03-28 01:13:20 +00:00
checked: StreamingPreferences . gameOptimizations
2018-07-09 05:56:38 +00:00
onCheckedChanged: {
2019-03-28 01:13:20 +00:00
StreamingPreferences . gameOptimizations = checked
2018-07-09 05:56:38 +00:00
}
2018-07-08 18:12:22 +00:00
}
CheckBox {
id: audioPcCheck
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Play audio on host PC" )
2018-07-08 18:12:22 +00:00
font.pointSize: 12
2019-03-28 01:13:20 +00:00
checked: StreamingPreferences . playAudioOnHost
2018-07-09 05:56:38 +00:00
onCheckedChanged: {
2019-03-28 01:13:20 +00:00
StreamingPreferences . playAudioOnHost = checked
2018-07-09 05:56:38 +00:00
}
2018-07-08 18:12:22 +00:00
}
2020-06-24 05:17:40 +00:00
CheckBox {
id: quitAppAfter
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Quit app on host PC after ending stream" )
2020-06-24 05:17:40 +00:00
font.pointSize: 12
checked: StreamingPreferences . quitAppAfter
onCheckedChanged: {
StreamingPreferences . quitAppAfter = checked
}
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered
2020-11-21 17:42:16 +00:00
ToolTip.text: qsTr ( "This will close the app or game you are streaming when you end your stream. You will lose any unsaved progress!" )
2020-06-24 05:17:40 +00:00
}
2018-07-08 18:12:22 +00:00
}
}
GroupBox {
id: advancedSettingsGroupBox
2020-05-10 20:02:10 +00:00
width: ( parent . width - ( parent . leftPadding + parent . rightPadding ) )
2018-07-08 18:12:22 +00:00
padding: 12
2020-11-21 19:15:54 +00:00
title: "<font color=\"skyblue\">" + qsTr ( "Advanced Settings" ) + "</font>"
2018-07-08 18:12:22 +00:00
font.pointSize: 12
Column {
anchors.fill: parent
spacing: 5
2018-07-20 21:14:38 +00:00
Label {
width: parent . width
id: resVDSTitle
text: qsTr ( "Video decoder" )
font.pointSize: 12
wrapMode: Text . Wrap
2018-07-08 18:12:22 +00:00
}
2018-07-20 21:14:38 +00:00
2018-10-06 19:12:05 +00:00
AutoResizingComboBox {
2018-07-20 21:14:38 +00:00
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
2019-03-28 01:13:20 +00:00
var saved_vds = StreamingPreferences . videoDecoderSelection
2018-07-20 21:14:38 +00:00
currentIndex = 0
2018-09-08 06:16:13 +00:00
for ( var i = 0 ; i < decoderListModel . count ; i ++ ) {
2018-07-20 21:14:38 +00:00
var el_vds = decoderListModel . get ( i ) . val ;
2018-09-08 06:16:13 +00:00
if ( saved_vds === el_vds ) {
currentIndex = i
break
}
2018-07-20 21:14:38 +00:00
}
2018-09-08 06:16:13 +00:00
activated ( currentIndex )
2018-07-20 21:14:38 +00:00
}
id: decoderComboBox
textRole: "text"
model: ListModel {
id: decoderListModel
ListElement {
2020-11-21 17:42:16 +00:00
text: qsTr ( "Automatic (Recommended)" )
2018-07-20 21:14:38 +00:00
val: StreamingPreferences . VDS_AUTO
}
ListElement {
2020-11-21 17:42:16 +00:00
text: qsTr ( "Force software decoding" )
2018-07-20 21:14:38 +00:00
val: StreamingPreferences . VDS_FORCE_SOFTWARE
}
ListElement {
2020-11-21 17:42:16 +00:00
text: qsTr ( "Force hardware decoding" )
2018-07-20 21:14:38 +00:00
val: StreamingPreferences . VDS_FORCE_HARDWARE
}
}
// ::onActivated must be used, as it only listens for when the index is changed by a human
onActivated : {
2019-03-28 01:13:20 +00:00
StreamingPreferences . videoDecoderSelection = decoderListModel . get ( currentIndex ) . val
2018-07-20 21:14:38 +00:00
}
}
2018-07-20 21:22:22 +00:00
Label {
width: parent . width
id: resVCCTitle
text: qsTr ( "Video codec" )
font.pointSize: 12
wrapMode: Text . Wrap
}
2018-10-06 19:12:05 +00:00
AutoResizingComboBox {
2018-07-20 21:22:22 +00:00
// ignore setting the index at first, and actually set it when the component is loaded
Component.onCompleted: {
2019-03-28 01:13:20 +00:00
var saved_vcc = StreamingPreferences . videoCodecConfig
2018-07-20 21:22:22 +00:00
currentIndex = 0
for ( var i = 0 ; i < codecListModel . count ; i ++ ) {
var el_vcc = codecListModel . get ( i ) . val ;
2018-09-08 06:16:13 +00:00
if ( saved_vcc === el_vcc ) {
currentIndex = i
break
}
2018-07-20 21:22:22 +00:00
}
2018-09-08 06:16:13 +00:00
activated ( currentIndex )
2018-07-20 21:22:22 +00:00
}
id: codecComboBox
textRole: "text"
model: ListModel {
id: codecListModel
ListElement {
2020-11-21 17:42:16 +00:00
text: qsTr ( "Automatic (Recommended)" )
2018-07-20 21:22:22 +00:00
val: StreamingPreferences . VCC_AUTO
}
ListElement {
2020-11-21 19:15:54 +00:00
text: qsTr ( "H.264" )
2018-07-20 21:22:22 +00:00
val: StreamingPreferences . VCC_FORCE_H264
}
ListElement {
2020-11-21 19:15:54 +00:00
text: qsTr ( "HEVC (H.265)" )
2018-07-20 21:22:22 +00:00
val: StreamingPreferences . VCC_FORCE_HEVC
}
2020-09-07 00:33:40 +00:00
/ * L i s t E l e m e n t {
2020-11-21 19:15:54 +00:00
text: qsTr ( "HEVC HDR (Experimental)" )
2018-07-20 21:22:22 +00:00
val: StreamingPreferences . VCC_FORCE_HEVC_HDR
2020-09-07 00:33:40 +00:00
} * /
2018-07-20 21:22:22 +00:00
}
// ::onActivated must be used, as it only listens for when the index is changed by a human
onActivated : {
2019-03-28 01:13:20 +00:00
StreamingPreferences . videoCodecConfig = codecListModel . get ( currentIndex ) . val
2018-07-20 21:22:22 +00:00
}
}
2018-09-08 21:33:34 +00:00
CheckBox {
id: unlockUnsupportedFps
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Unlock unsupported FPS options" )
2018-09-08 21:33:34 +00:00
font.pointSize: 12
2019-03-28 01:13:20 +00:00
checked: StreamingPreferences . unsupportedFps
2018-09-08 21:33:34 +00:00
onCheckedChanged: {
2019-03-25 02:15:35 +00:00
// This is called on init, so only do the work if we've
// actually changed the value.
2019-03-28 01:13:20 +00:00
if ( StreamingPreferences . unsupportedFps != checked ) {
StreamingPreferences . unsupportedFps = checked
2019-03-25 02:15:35 +00:00
// The selectable FPS values depend on whether
// this option is enabled or not
fpsComboBox . reinitialize ( )
}
2018-09-08 21:33:34 +00:00
}
}
2018-09-09 19:33:19 +00:00
CheckBox {
id: enableMdns
2020-05-10 18:12:37 +00:00
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Automatically find PCs on the local network (Recommended)" )
2018-09-09 19:33:19 +00:00
font.pointSize: 12
2019-03-28 01:13:20 +00:00
checked: StreamingPreferences . enableMdns
2018-09-09 19:33:19 +00:00
onCheckedChanged: {
2019-03-25 02:15:35 +00:00
// This is called on init, so only do the work if we've
// actually changed the value.
2019-03-28 01:13:20 +00:00
if ( StreamingPreferences . enableMdns != checked ) {
StreamingPreferences . enableMdns = checked
2019-03-25 02:15:35 +00:00
// We must save the updated preference to ensure
// ComputerManager can observe the change internally.
2019-03-28 01:13:20 +00:00
StreamingPreferences . save ( )
2019-03-25 02:15:35 +00:00
// Restart polling so the mDNS change takes effect
if ( window . pollingActive ) {
ComputerManager . stopPollingAsync ( )
ComputerManager . startPolling ( )
}
2018-09-09 19:33:19 +00:00
}
}
}
2020-08-09 01:29:36 +00:00
CheckBox {
id: detectNetworkBlocking
width: parent . width
2020-11-21 17:42:16 +00:00
text: qsTr ( "Automatically detect blocked connections (Recommended)" )
2020-08-09 01:29:36 +00:00
font.pointSize: 12
checked: StreamingPreferences . detectNetworkBlocking
onCheckedChanged: {
// This is called on init, so only do the work if we've
// actually changed the value.
if ( StreamingPreferences . detectNetworkBlocking != checked ) {
StreamingPreferences . detectNetworkBlocking = checked
// We must save the updated preference to ensure
// ComputerManager can observe the change internally.
StreamingPreferences . save ( )
}
}
}
2018-07-08 17:19:08 +00:00
}
}
}
2018-07-08 05:15:02 +00:00
}