Skip to content

Commit 29b457d

Browse files
committed
Put MediaPlayer's error handler back in Qt 5 spelling, and teach the generator the rename
The Android app has been coming up with an empty window since c3bd6e8, and not because of anything to do with a bike. Home.qml assigns onErrorOccurred, which is Qt 6's name for MediaPlayer's error signal. Qt 5.15 has no such property, and assigning to one that does not exist is a load error rather than a warning - so Home.qml never instantiates, StackView is left with no initialItem, and the window is blank while the app runs perfectly well behind it. The device log says it in one line: qrc:/main.qml:1420:9: QML StackView: initialItem: qrc:/Home.qml:625 Cannot assign to non-existent property "onErrorOccurred" and then says it again in the consequences: rootItem undefined all over HomeForm.ui.qml, and homeform's constructor connecting its QML signals to (nullptr) eight times over, because rootObject->findChild("home") found nothing to connect to. tools/qt6-qml-imports.py already carries the rule this broke, in its own docstring: the sources are Qt 5, because Qt 5 is what Android and every other shipping target build, and the Qt 6 variants are generated. Imports were the only difference it knew about. Renamed signal handlers are a second, so it now rewrites those too - anchored to the start of a line and matched with its colon, so the same word in a comment is left alone. The body becomes a plain function expression rather than either version's parameter syntax, because Qt 5 injects signal parameters and Qt 6 removed injection, and a function is the one form both bind correctly. videoOutput, which the same commit introduced, needs no such treatment: Qt 5.15's own type registration lists it at revision 15, and the device log never complained about it. The error was always just the one property. Verified on Qt 5.15 by running the app: the load error is gone, and the eight connect-to-nullptr failures are zero, which is the same thing said from the C++ side - Home.qml loads and findChild("home") finds it. Checked the other direction too, by running the generator over the fixed source and confirming the Qt 6 output carries onErrorOccurred, so the Windows build keeps what c3bd6e8 gave it. src/videoPlayback.qml carried the same two lines and gets the same change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019d4Hga7UGcxmcG88pwcSCV
1 parent d749ca0 commit 29b457d

3 files changed

Lines changed: 35 additions & 8 deletions

File tree

src/Home.qml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -611,18 +611,26 @@ HomeForm {
611611
}
612612
}
613613

614-
// Qt 6 renamed the error signal to errorOccurred() and reversed how the
615-
// sink is attached: the player names its videoOutput rather than the
616-
// VideoOutput naming its source. Assigning to the old onError is a load
617-
// error, not a warning - it takes Home.qml with it, and StackView then
618-
// has no initialItem, which is why the window came up empty.
614+
// Qt 6 renamed this signal from error() to errorOccurred(). The Qt 5
615+
// spelling is the one that belongs here - these sources are Qt 5 and the
616+
// Qt 6 variants are generated (tools/qt6-qml-imports.py, which does the
617+
// rename) - because Qt 5.15 has no errorOccurred and rejects the
618+
// assignment outright. That is a load error rather than a warning, so it
619+
// takes Home.qml with it, StackView is left with no initialItem, and the
620+
// Android window comes up empty with the app running fine underneath.
621+
//
622+
// The body is a function expression rather than either version's parameter
623+
// syntax: Qt 5 injects signal parameters and Qt 6 removed injection, and a
624+
// plain function is the one form both bind correctly.
625+
//
626+
// videoOutput needs no such care - it exists in Qt 5.15 too (revision 15).
619627
MediaPlayer {
620628
id: videoPlaybackHalf
621629
objectName: "videoplaybackhalf"
622630
playbackRate: rootItem.videoRate
623631
videoOutput: videoPlayer
624632

625-
onErrorOccurred: (error, errorString) => {
633+
onError: function(error, errorString) {
626634
if (MediaPlayer.NoError !== error) {
627635
console.log("[qmlvideo] MediaPlayer error " + error + " errorString " + errorString)
628636
}

src/videoPlayback.qml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Rectangle {
2222
playbackRate: rootItem.videoRate
2323
videoOutput: videoPlayer
2424

25-
onErrorOccurred: (error, errorString) => {
25+
onError: function(error, errorString) {
2626
if (MediaPlayer.NoError !== error) {
2727
console.log("[qmlvideo] MediaPlayer error " + error + " errorString " + errorString)
2828
}

tools/qt6-qml-imports.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env python3
2-
"""Rewrite the QML import lines for a Qt 6 build.
2+
"""Rewrite the QML imports, and the handful of renamed signal handlers, for a Qt 6 build.
33
44
The .qml sources are written for Qt 5, which is what Android, iOS and every other
55
shipping target build with. Qt 5.15 refuses a library import that carries no
@@ -40,6 +40,19 @@
4040
# QtQuick, QtQuick.Controls, QtQuick.Layouts and QtQuick.Window are deliberately
4141
# absent from both tables: Qt 6 still accepts their 2.x imports.
4242

43+
# Signal handlers Qt 6 renamed. Same principle as the imports: the Qt 5 spelling is
44+
# what the sources carry, because Qt 5 is what ships, and Qt 6 is generated.
45+
#
46+
# MediaPlayer's error() became errorOccurred(). Writing the Qt 6 name in the source
47+
# instead does not degrade gracefully - Qt 5.15 has no such property, so assigning to
48+
# it is a *load* error that takes the whole file with it. When that file is Home.qml,
49+
# StackView has no initialItem and the Android app comes up with an empty window and
50+
# no clue as to why. That is not hypothetical; it shipped, and cost an evening.
51+
#
52+
# Anchored to the start of a line so a mention inside a string or a comment is left
53+
# alone, and matched with the colon so it is a handler and not a word.
54+
HANDLER_RENAME = {"onError": "onErrorOccurred"}
55+
4356
VERSION = r"[0-9]+(?:\.[0-9]+)?"
4457

4558

@@ -56,6 +69,12 @@ def rewrite(text):
5669
r"\g<1>",
5770
text,
5871
)
72+
for handler, replacement in HANDLER_RENAME.items():
73+
text = re.sub(
74+
rf"(?m)^(\s*){re.escape(handler)}(\s*:)",
75+
rf"\g<1>{replacement}\g<2>",
76+
text,
77+
)
5978
return text
6079

6180

0 commit comments

Comments
 (0)