From 2b3e0803de0595d95bf958abb60adb9d0e2be4d6 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 11 Oct 2025 11:03:33 -0500 Subject: [PATCH] Increase Qt requirement to 5.12 and remove pre-5.12 workarounds --- README.md | 4 ++-- app/backend/computermanager.cpp | 10 ++-------- app/gui/AppView.qml | 12 ++++-------- app/gui/CenteredGridView.qml | 18 ------------------ app/gui/NavigableMenuItem.qml | 8 ++------ app/gui/PcView.qml | 8 +------- app/gui/main.qml | 22 ++++++---------------- 7 files changed, 17 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index b4f12b62..e9f63890 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Hosting for Moonlight's Debian and L4T package repositories is graciously provid * [create-dmg](https://github.com/sindresorhus/create-dmg) (only if building DMGs for use on non-development Macs) ### Linux/Unix Build Requirements -* Qt 6 is recommended, but Qt 5.9 or later is also supported (replace `qmake6` with `qmake` when using Qt 5). +* Qt 6 is recommended, but Qt 5.12 or later is also supported (replace `qmake6` with `qmake` when using Qt 5). * GCC or Clang * FFmpeg 4.0 or later * Install the required packages: @@ -75,7 +75,7 @@ Hosting for Moonlight's Debian and L4T package repositories is graciously provid ### Build Setup Steps 1. Install the latest Qt SDK (and optionally, the Qt Creator IDE) from https://www.qt.io/download * You can install Qt via Homebrew on macOS, but you will need to use `brew install qt --with-debug` to be able to create debug builds of Moonlight. - * You may also use your Linux distro's package manager for the Qt SDK as long as the packages are Qt 5.9 or later. + * You may also use your Linux distro's package manager for the Qt SDK as long as the packages are Qt 5.12 or later. * This step is not required for building on Steam Link, because the Steam Link SDK includes Qt 5.14. 2. Run `git submodule update --init --recursive` from within `moonlight-qt/` 3. Open the project in Qt Creator or build from qmake on the command line. diff --git a/app/backend/computermanager.cpp b/app/backend/computermanager.cpp index 7e03d61d..1f59b74f 100644 --- a/app/backend/computermanager.cpp +++ b/app/backend/computermanager.cpp @@ -9,8 +9,7 @@ #include #include #include - -#include +#include #define SER_HOSTS "hosts" #define SER_HOSTS_BACKUP "hostsbackup" @@ -966,14 +965,9 @@ void ComputerManager::addNewHost(NvAddress address, bool mdns, NvAddress mdnsIpv QThreadPool::globalInstance()->start(addTask); } -// TODO: Use QRandomGenerator when we drop Qt 5.9 support QString ComputerManager::generatePinString() { - std::uniform_int_distribution dist(0, 9999); - std::random_device rd; - std::mt19937 engine(rd()); - - return QString::asprintf("%04u", dist(engine)); + return QString::asprintf("%04u", QRandomGenerator::system()->bounded(10000)); } #include "computermanager.moc" diff --git a/app/gui/AppView.qml b/app/gui/AppView.qml index 3bcdf6d5..74a6a38c 100644 --- a/app/gui/AppView.qml +++ b/app/gui/AppView.qml @@ -38,7 +38,7 @@ CenteredGridView { activated = true // Highlight the first item if a gamepad is connected - if (currentIndex == -1 && SdlGamepadKeyNavigation.getConnectedGamepads() > 0) { + if (currentIndex === -1 && SdlGamepadKeyNavigation.getConnectedGamepads() > 0) { currentIndex = 0 } @@ -94,9 +94,9 @@ CenteredGridView { // the image size checks if this is not an app collector game. We know the officially // supported games all have box art, so this check is not required. if (!model.isAppCollectorGame && - ((sourceSize.width == 130 && sourceSize.height == 180) || // GFE 2.0 placeholder image - (sourceSize.width == 628 && sourceSize.height == 888) || // GFE 3.0 placeholder image - (sourceSize.width == 200 && sourceSize.height == 266))) // Our no_app_image.png + ((sourceSize.width === 130 && sourceSize.height === 180) || // GFE 2.0 placeholder image + (sourceSize.width === 628 && sourceSize.height === 888) || // GFE 3.0 placeholder image + (sourceSize.width === 200 && sourceSize.height === 266))) // Our no_app_image.png { isPlaceholder = true } @@ -299,18 +299,15 @@ CenteredGridView { sourceComponent: NavigableMenu { id: appContextMenu NavigableMenuItem { - parentMenu: appContextMenu text: model.running ? qsTr("Resume Game") : qsTr("Launch Game") onTriggered: launchOrResumeSelectedApp(true) } NavigableMenuItem { - parentMenu: appContextMenu text: qsTr("Quit Game") onTriggered: doQuitGame() visible: model.running } NavigableMenuItem { - parentMenu: appContextMenu checkable: true checked: model.directLaunch text: qsTr("Direct Launch") @@ -323,7 +320,6 @@ CenteredGridView { ToolTip.visible: hovered } NavigableMenuItem { - parentMenu: appContextMenu checkable: true checked: model.hidden text: qsTr("Hide Game") diff --git a/app/gui/CenteredGridView.qml b/app/gui/CenteredGridView.qml index ba2b6569..fb5f51f4 100644 --- a/app/gui/CenteredGridView.qml +++ b/app/gui/CenteredGridView.qml @@ -2,10 +2,6 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 GridView { - // Detect Qt 5.11 or earlier using presence of synchronousDrag. - // Prior to 5.12, the leftMargin and rightMargin values did not work. - property bool hasBrokenMargins: this.synchronousDrag === undefined - property int minMargin: 10 property real availableWidth: (parent.width - 2 * minMargin) property int itemsPerRow: availableWidth / cellWidth @@ -15,11 +11,6 @@ GridView { function updateMargins() { leftMargin = horizontalMargin rightMargin = horizontalMargin - - if (hasBrokenMargins) { - anchors.leftMargin = leftMargin - anchors.rightMargin = rightMargin - } } onHorizontalMarginChanged: { @@ -27,15 +18,6 @@ GridView { } Component.onCompleted: { - if (hasBrokenMargins) { - // This will cause an anchor conflict with the parent StackView - // which breaks animation, but otherwise the grid will not be - // centered in the window. - anchors.fill = parent - anchors.topMargin = topMargin - anchors.bottomMargin = bottomMargin - } - updateMargins() } diff --git a/app/gui/NavigableMenuItem.qml b/app/gui/NavigableMenuItem.qml index f1df3a77..aeb45eac 100644 --- a/app/gui/NavigableMenuItem.qml +++ b/app/gui/NavigableMenuItem.qml @@ -2,10 +2,6 @@ import QtQuick 2.0 import QtQuick.Controls 2.2 MenuItem { - // Qt 5.10 has a menu property, but we need to support 5.9 - // so we must make our own. - property Menu parentMenu - // Ensure focus can't be given to an invisible item enabled: visible height: visible ? implicitHeight : 0 @@ -15,7 +11,7 @@ MenuItem { // We must close the context menu first or // it can steal focus from any dialogs that // onTriggered may spawn. - parentMenu.close() + menu.close() } Keys.onReturnPressed: { @@ -27,6 +23,6 @@ MenuItem { } Keys.onEscapePressed: { - parentMenu.close() + menu.close() } } diff --git a/app/gui/PcView.qml b/app/gui/PcView.qml index 79dc0f5e..43962d17 100644 --- a/app/gui/PcView.qml +++ b/app/gui/PcView.qml @@ -35,7 +35,7 @@ CenteredGridView { ComputerManager.computerAddCompleted.connect(addComplete) // Highlight the first item if a gamepad is connected - if (currentIndex == -1 && SdlGamepadKeyNavigation.getConnectedGamepads() > 0) { + if (currentIndex === -1 && SdlGamepadKeyNavigation.getConnectedGamepads() > 0) { currentIndex = 0 } } @@ -169,7 +169,6 @@ CenteredGridView { enabled: false } NavigableMenuItem { - parentMenu: pcContextMenu text: qsTr("View All Apps") onTriggered: { var component = Qt.createComponent("AppView.qml") @@ -179,13 +178,11 @@ CenteredGridView { visible: model.online && model.paired } NavigableMenuItem { - parentMenu: pcContextMenu text: qsTr("Wake PC") onTriggered: computerModel.wakeComputer(index) visible: !model.online && model.wakeable } NavigableMenuItem { - parentMenu: pcContextMenu text: qsTr("Test Network") onTriggered: { computerModel.testConnectionForComputer(index) @@ -194,7 +191,6 @@ CenteredGridView { } NavigableMenuItem { - parentMenu: pcContextMenu text: qsTr("Rename PC") onTriggered: { renamePcDialog.pcIndex = index @@ -203,7 +199,6 @@ CenteredGridView { } } NavigableMenuItem { - parentMenu: pcContextMenu text: qsTr("Delete PC") onTriggered: { deletePcDialog.pcIndex = index @@ -212,7 +207,6 @@ CenteredGridView { } } NavigableMenuItem { - parentMenu: pcContextMenu text: qsTr("View Details") onTriggered: { showPcDetailsDialog.pcDetails = model.details diff --git a/app/gui/main.qml b/app/gui/main.qml index 54aefe8f..dc50c3a0 100644 --- a/app/gui/main.qml +++ b/app/gui/main.qml @@ -205,20 +205,10 @@ ApplicationWindow { SdlGamepadKeyNavigation.notifyWindowFocus(visible && active) } - // Workaround for lack of instanceof in Qt 5.9. - // - // Based on https://stackoverflow.com/questions/13923794/how-to-do-a-is-a-typeof-or-instanceof-in-qml - function qmltypeof(obj, className) { // QtObject, string -> bool - // className plus "(" is the class instance without modification - // className plus "_QML" is the class instance with user-defined properties - var str = obj.toString(); - return str.startsWith(className + "(") || str.startsWith(className + "_QML"); - } - function navigateTo(url, objectType) { var existingItem = stackView.find(function(item, index) { - return qmltypeof(item, objectType) + return item instanceof objectType }) if (existingItem !== null) { @@ -285,7 +275,7 @@ ApplicationWindow { Label { id: versionLabel - visible: qmltypeof(stackView.currentItem, "SettingsView") + visible: stackView.currentItem instanceof SettingsView text: qsTr("Version %1").arg(SystemProperties.versionString) font.pointSize: 12 horizontalAlignment: Qt.AlignRight @@ -295,7 +285,7 @@ ApplicationWindow { NavigableToolButton { id: discordButton visible: SystemProperties.hasBrowser && - qmltypeof(stackView.currentItem, "SettingsView") + stackView.currentItem instanceof SettingsView iconSource: "qrc:/res/discord.svg" @@ -314,7 +304,7 @@ ApplicationWindow { NavigableToolButton { id: addPcButton - visible: qmltypeof(stackView.currentItem, "PcView") + visible: stackView.currentItem instanceof PcView iconSource: "qrc:/res/ic_add_to_queue_white_48px.svg" @@ -412,7 +402,7 @@ ApplicationWindow { iconSource: "qrc:/res/ic_videogame_asset_white_48px.svg" - onClicked: navigateTo("qrc:/gui/GamepadMapper.qml", "GamepadMapper") + onClicked: navigateTo("qrc:/gui/GamepadMapper.qml", GamepadMapper) Keys.onDownPressed: { stackView.currentItem.forceActiveFocus(Qt.TabFocus) @@ -424,7 +414,7 @@ ApplicationWindow { iconSource: "qrc:/res/settings.svg" - onClicked: navigateTo("qrc:/gui/SettingsView.qml", "SettingsView") + onClicked: navigateTo("qrc:/gui/SettingsView.qml", SettingsView) Keys.onDownPressed: { stackView.currentItem.forceActiveFocus(Qt.TabFocus)