diff options
author | Oliver Eftevaag <oliver.eftevaag@qt.io> | 2024-01-04 14:25:42 +0100 |
---|---|---|
committer | Oliver Eftevaag <oliver.eftevaag@qt.io> | 2024-04-04 11:00:37 +0200 |
commit | 6e6fe9862aed124176a79027a92871fde49c0817 (patch) | |
tree | 5ca36b1bdf35167c9b16de14cb84b0eb22692a5f | |
parent | 2d7d8772764a0eaf0e2f300b4cb639ca0b3c1071 (diff) |
Revamp qmlvideo example
In order to make the example adhere to our example guidelines,
and to encourage the use of QML best practices. I've made numerous
improvements in this patch. Which contains the following changes.
- All root and context properties are replaced with a singleton.
- User facing strings are wrapped with qsTr().
- QtQuick.Controls buttons are now used, instead of the homemade
Button.qml.
- We're now using colors from the palette, instead of hard coded color values.
- QtQuick.Layouts are now used, where it makes sense.
- Most qmllint warnings are now fixed, with a few being suppressed with
qmllint enable/disable comments.
Fixes: QTBUG-113689
Pick-to: 6.7
Change-Id: I685d68665657f631cba4d8f83519ca2ecc45e2d8
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
47 files changed, 423 insertions, 403 deletions
diff --git a/examples/multimedia/video/qmlvideo/CMakeLists.txt b/examples/multimedia/video/qmlvideo/CMakeLists.txt index fc7e2bd10..43975d584 100644 --- a/examples/multimedia/video/qmlvideo/CMakeLists.txt +++ b/examples/multimedia/video/qmlvideo/CMakeLists.txt @@ -36,18 +36,21 @@ target_compile_definitions(qmlvideoexample PUBLIC PERFORMANCEMONITOR_SUPPORT ) +add_subdirectory(qmlvideo) +add_subdirectory(performancemonitor) +add_subdirectory(frequencymonitor) + target_link_libraries(qmlvideoexample PRIVATE Qt::Core Qt::Gui Qt::Multimedia Qt::Qml Qt::Quick + qmlvideo + performancemonitor + frequencymonitor ) -add_subdirectory(qmlvideo) -add_subdirectory(performancemonitor) -add_subdirectory(frequencymonitor) - install(TARGETS qmlvideoexample RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" diff --git a/examples/multimedia/video/qmlvideo/main.cpp b/examples/multimedia/video/qmlvideo/main.cpp index 15df44dd2..94c5bfea0 100644 --- a/examples/multimedia/video/qmlvideo/main.cpp +++ b/examples/multimedia/video/qmlvideo/main.cpp @@ -3,6 +3,7 @@ #include "performancemonitor.h" #include "trace.h" +#include "qmlvideo/videosingleton.h" #ifdef PERFORMANCEMONITOR_SUPPORT # include "performancemonitordeclarative.h" #endif @@ -78,16 +79,21 @@ int main(int argc, char *argv[]) url2 = QUrl::fromLocalFile(source2); } + const QStringList moviesLocation = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation); + const QUrl videoPath = QUrl::fromLocalFile(moviesLocation.isEmpty() ? app.applicationDirPath() + : moviesLocation.front()); + QQuickView viewer; + VideoSingleton* singleton = viewer.engine()->singletonInstance<VideoSingleton*>("qmlvideo", "VideoSingleton"); + singleton->setVideoPath(videoPath); + singleton->setSource1(source1); + singleton->setSource2(source2); + singleton->setVolume(volume); viewer.loadFromModule("qmlvideo", "Main"); QObject::connect(viewer.engine(), &QQmlEngine::quit, &viewer, &QQuickView::close); - QQuickItem *rootObject = viewer.rootObject(); - rootObject->setProperty("source1", url1); - rootObject->setProperty("source2", url2); - rootObject->setProperty("volume", volume); - #ifdef PERFORMANCEMONITOR_SUPPORT + QQuickItem *rootObject = viewer.rootObject(); if (performanceMonitorState.valid) { rootObject->setProperty("perfMonitorsLogging", performanceMonitorState.logging); rootObject->setProperty("perfMonitorsVisible", performanceMonitorState.visible); @@ -95,12 +101,6 @@ int main(int argc, char *argv[]) QObject::connect(&viewer, SIGNAL(afterRendering()), rootObject, SLOT(qmlFramePainted())); #endif - const QStringList moviesLocation = - QStandardPaths::standardLocations(QStandardPaths::MoviesLocation); - const QUrl videoPath = QUrl::fromLocalFile(moviesLocation.isEmpty() ? app.applicationDirPath() - : moviesLocation.front()); - viewer.rootContext()->setContextProperty("videoPath", videoPath); - QMetaObject::invokeMethod(rootObject, "init"); auto setupView = [&viewer]() { diff --git a/examples/multimedia/video/qmlvideo/performancemonitor/PerformanceItem.qml b/examples/multimedia/video/qmlvideo/performancemonitor/PerformanceItem.qml index 12253be62..5b501b104 100644 --- a/examples/multimedia/video/qmlvideo/performancemonitor/PerformanceItem.qml +++ b/examples/multimedia/video/qmlvideo/performancemonitor/PerformanceItem.qml @@ -41,8 +41,7 @@ Rectangle { State { name: "hidden" PropertyChanges { - target: root - opacity: 0 + root.opacity: 0 } } ] @@ -64,19 +63,19 @@ Rectangle { function createQmlFrameRateItem() { let component = Qt.createComponent("frequencymonitor", "FrequencyItem") if (component.status === Component.Ready) - d.qmlFrameRateItem = component.createObject(column, { label: "QML frame rate", - displayed: root.displayed, + d.qmlFrameRateItem = component.createObject(column, { label: qsTr("QML frame rate"), + displayed: root.displayed, logging: root.logging - }) + }); } function createVideoFrameRateItem() { let component = Qt.createComponent("frequencymonitor", "FrequencyItem") if (component.status === Component.Ready) - d.videoFrameRateItem = component.createObject(column, { label: "Video frame rate", - displayed: root.displayed, + d.videoFrameRateItem = component.createObject(column, { label: qsTr("Video frame rate"), + displayed: root.displayed, logging: root.logging - }) + }); videoFrameRateActiveConnections.target = d.videoFrameRateItem } @@ -87,13 +86,11 @@ Rectangle { } function videoFramePainted() { - if (d.videoFrameRateItem) - d.videoFrameRateItem.notify() + d.videoFrameRateItem?.notify() } function qmlFramePainted() { - if (d.qmlFrameRateItem) - d.qmlFrameRateItem.notify() + d.qmlFrameRateItem?.notify() } onVideoActiveChanged: { diff --git a/examples/multimedia/video/qmlvideo/qmlvideo.pro b/examples/multimedia/video/qmlvideo/qmlvideo.pro index cabdddbe0..b61339264 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo.pro +++ b/examples/multimedia/video/qmlvideo/qmlvideo.pro @@ -12,27 +12,29 @@ DEFINES += \ PERFORMANCEMONITOR_SUPPORT SOURCES += \ - main.cpp \ frequencymonitor.cpp \ frequencymonitordeclarative.cpp \ + main.cpp \ performancemonitor.cpp \ - performancemonitordeclarative.cpp + performancemonitordeclarative.cpp \ + qmlvideo/videosingleton.cpp + +INCLUDEPATH += qmlvideo + +DEFINES += QMLVIDEO_LIB HEADERS += \ - trace.h \ frequencymonitor.h \ performancemonitor.h \ - performancemonitordeclarative.h + performancemonitordeclarative.h \ + trace.h \ + qmlvideo/videosingleton.h resources.files = \ - qmlvideo/images/folder.png \ - qmlvideo/images/leaves.jpg \ - qmlvideo/images/up.png \ frequencymonitor/FrequencyItem.qml \ frequencymonitor/qmldir \ performancemonitor/PerformanceItem.qml \ performancemonitor/qmldir \ - qmlvideo/Button.qml \ qmlvideo/CameraBasic.qml \ qmlvideo/CameraDrag.qml \ qmlvideo/CameraDummy.qml \ @@ -46,6 +48,7 @@ resources.files = \ qmlvideo/CameraSpin.qml \ qmlvideo/Content.qml \ qmlvideo/ErrorDialog.qml \ + qmlvideo/Main.qml \ qmlvideo/Scene.qml \ qmlvideo/SceneBasic.qml \ qmlvideo/SceneDrag.qml \ @@ -74,13 +77,19 @@ resources.files = \ qmlvideo/VideoRotate.qml \ qmlvideo/VideoSeek.qml \ qmlvideo/VideoSpin.qml \ - qmlvideo/Main.qml \ + qmlvideo/images/folder.png \ + qmlvideo/images/leaves.jpg \ + qmlvideo/images/up.png \ qmlvideo/qmldir resources.prefix = /qt/qml/ RESOURCES += resources +CONFIG += qmltypes +QML_IMPORT_NAME = qmlvideo +QML_IMPORT_MAJOR_VERSION = 1 + target.path = $$[QT_INSTALL_EXAMPLES]/multimedia/video/qmlvideo INSTALLS += target diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/Button.qml b/examples/multimedia/video/qmlvideo/qmlvideo/Button.qml deleted file mode 100644 index 3e33d418a..000000000 --- a/examples/multimedia/video/qmlvideo/qmlvideo/Button.qml +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -import QtQuick - -Item { - id: root - - property string text - property color bgColor: "#757575" - property color bgColorSelected: "#bdbdbd" - property color textColor: "white" - property color textColorSelected: "black" - property alias enabled: mouseArea.enabled - property alias radius: bgr.radius - - signal clicked - - Rectangle { - id: bgr - anchors.fill: parent - color: mouseArea.pressed ? bgColorSelected : bgColor - radius: height / 15 - - Text { - id: text - anchors.centerIn: parent - text: root.text - font.pixelSize: 0.4 * parent.height - color: mouseArea.pressed ? textColorSelected : textColor - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - - MouseArea { - id: mouseArea - anchors.fill: parent - onClicked: { - root.clicked() - } - } - } -} diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CMakeLists.txt b/examples/multimedia/video/qmlvideo/qmlvideo/CMakeLists.txt index f81a29386..84a65710e 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CMakeLists.txt +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CMakeLists.txt @@ -9,8 +9,11 @@ set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/multimedia/video/qmlvideo/qmlvide qt_add_qml_module(qmlvideo URI qmlvideo + SOURCES + videosingleton.cpp + videosingleton.h + qmlvideo_global.h QML_FILES - "Button.qml" "CameraBasic.qml" "CameraDrag.qml" "CameraDummy.qml" @@ -24,6 +27,7 @@ qt_add_qml_module(qmlvideo "CameraSpin.qml" "Content.qml" "ErrorDialog.qml" + "Main.qml" "Scene.qml" "SceneBasic.qml" "SceneDrag.qml" @@ -52,13 +56,14 @@ qt_add_qml_module(qmlvideo "VideoRotate.qml" "VideoSeek.qml" "VideoSpin.qml" - "Main.qml" RESOURCES "images/folder.png" "images/leaves.jpg" "images/up.png" ) +target_compile_definitions(qmlvideo PRIVATE QMLVIDEO_LIB) + target_link_libraries(qmlvideo PRIVATE Qt6::Core Qt6::Gui diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CameraBasic.qml b/examples/multimedia/video/qmlvideo/qmlvideo/CameraBasic.qml index 4c85f358c..77072c6c9 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CameraBasic.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CameraBasic.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneBasic { contentType: "camera" started: true diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CameraDrag.qml b/examples/multimedia/video/qmlvideo/qmlvideo/CameraDrag.qml index a733548dd..2ea3672c6 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CameraDrag.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CameraDrag.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneDrag { contentType: "camera" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CameraDummy.qml b/examples/multimedia/video/qmlvideo/qmlvideo/CameraDummy.qml index cf59c04f1..c9d14e595 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CameraDummy.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CameraDummy.qml @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls // Item which is loaded by CameraItem if Qt Multimedia is not available Rectangle { @@ -13,12 +14,11 @@ Rectangle { signal sizeChanged signal framePainted - Text { + Label { anchors.fill: parent anchors.margins: 10 - color: "white" horizontalAlignment: Text.AlignHCenter - text: "Failed to create Camera item\n\nCheck that Qt Multimedia is installed" + text: qsTr("Failed to create Camera item\n\nCheck that Qt Multimedia is installed") verticalAlignment: Text.AlignVCenter wrapMode: Text.Wrap } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CameraFullScreen.qml b/examples/multimedia/video/qmlvideo/qmlvideo/CameraFullScreen.qml index 03e3d2661..b204e74ab 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CameraFullScreen.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CameraFullScreen.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneFullScreen { contentType: "camera" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CameraFullScreenInverted.qml b/examples/multimedia/video/qmlvideo/qmlvideo/CameraFullScreenInverted.qml index dd6874f16..ff7a40253 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CameraFullScreenInverted.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CameraFullScreenInverted.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneFullScreenInverted { contentType: "camera" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CameraMove.qml b/examples/multimedia/video/qmlvideo/qmlvideo/CameraMove.qml index 1f7db298b..c4c5da914 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CameraMove.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CameraMove.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneMove { contentType: "camera" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CameraOverlay.qml b/examples/multimedia/video/qmlvideo/qmlvideo/CameraOverlay.qml index 3b152ca5d..13136be00 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CameraOverlay.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CameraOverlay.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneOverlay { contentType: "camera" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CameraResize.qml b/examples/multimedia/video/qmlvideo/qmlvideo/CameraResize.qml index 327541982..d89eef3ad 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CameraResize.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CameraResize.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneResize { contentType: "camera" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CameraRotate.qml b/examples/multimedia/video/qmlvideo/qmlvideo/CameraRotate.qml index 86cac7a1b..8394fb6fd 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CameraRotate.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CameraRotate.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneRotate { contentType: "camera" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/CameraSpin.qml b/examples/multimedia/video/qmlvideo/qmlvideo/CameraSpin.qml index 55a51430d..642a0edfd 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/CameraSpin.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/CameraSpin.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneSpin { contentType: "camera" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/Content.qml b/examples/multimedia/video/qmlvideo/qmlvideo/Content.qml index b808002e1..b08d19325 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/Content.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/Content.qml @@ -6,7 +6,7 @@ import frequencymonitor Rectangle { id: root - border.color: "white" + border.color: palette.window border.width: showBorder ? 1 : 0 color: "transparent" property string contentType // "camera" or "video" @@ -17,6 +17,7 @@ Rectangle { property bool started: false property bool showFrameRate: false property bool showBorder: false + property alias contentItem: contentLoader.item signal initialized signal error @@ -29,8 +30,7 @@ Rectangle { Connections { id: framePaintedConnection function onFramePainted() { - if (frameRateLoader.item) - frameRateLoader.item.notify() + (frameRateLoader.item as FrequencyItem)?.notify() root.videoFramePainted() } ignoreUnknownSignals: true @@ -40,15 +40,20 @@ Rectangle { id: errorConnection function onFatalError() { console.log("[qmlvideo] Content.onFatalError") - stop() + root.stop() root.error() } ignoreUnknownSignals: true } + Component { + id: frequencyItem + FrequencyItem {} + } + Loader { id: frameRateLoader - sourceComponent: root.showFrameRate ? FrequencyItem : undefined + sourceComponent: root.showFrameRate ? frequencyItem : undefined onLoaded: { item.parent = root item.anchors.top = root.top @@ -58,13 +63,13 @@ Rectangle { } onWidthChanged: { - if (contentItem()) - contentItem().width = width + if (root.contentItem) + root.contentItem.width = width } onHeightChanged: { - if (contentItem()) - contentItem().height = height + if (root.contentItem) + root.contentItem.height = height } function initialize() { @@ -105,6 +110,7 @@ Rectangle { } } + // qmllint disable function stop() { if (contentLoader.item) { contentLoader.item.stop() @@ -113,7 +119,7 @@ Rectangle { root.started = false } } + // qmllint enable - function contentItem() { return contentLoader.item } - function updateRootSize() { root.height = contentItem().height } + function updateRootSize() { root.height = (root.contentItem as Item).height } } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/ErrorDialog.qml b/examples/multimedia/video/qmlvideo/qmlvideo/ErrorDialog.qml index ce79b150f..f06079a35 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/ErrorDialog.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/ErrorDialog.qml @@ -16,8 +16,7 @@ Rectangle { State { name: "on" PropertyChanges { - target: root - opacity: 1.0 + root.opacity: 1.0 } } ] @@ -42,8 +41,8 @@ Rectangle { Rectangle { anchors.centerIn: parent - width: dialogWidth - height: dialogHeight + width: root.dialogWidth + height: root.dialogHeight radius: 5 color: "white" diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/Main.qml b/examples/multimedia/video/qmlvideo/qmlvideo/Main.qml index aabafcb2c..49b94590c 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/Main.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/Main.qml @@ -2,43 +2,39 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls +import QtQuick.Layouts import QtQuick.Dialogs import performancemonitor Rectangle { id: root anchors.fill: parent - color: "black" + color: palette.window - property string source1 - property string source2 - property color bgColor: "black" - property real volume: 0.25 property bool perfMonitorsLogging: false property bool perfMonitorsVisible: false - QtObject { - id: d - property int itemHeight: root.height > root.width ? root.width / 10 : root.height / 10 - property int buttonHeight: 0.8 * itemHeight - property int margins: 5 - } - Loader { id: performanceLoader Connections { - target: inner + target: columnLayout function onVisibleChanged() { if (performanceLoader.item) - performanceLoader.item.enabled = !inner.visible + performanceLoader.item.enabled = !columnLayout.visible } ignoreUnknownSignals: true } + Component { + id: performanceItem + PerformanceItem {} + } + function init() { var enabled = root.perfMonitorsLogging || root.perfMonitorsVisible - sourceComponent = enabled ? PerformanceItem : undefined + sourceComponent = enabled ? performanceItem : undefined } onLoaded: { @@ -51,106 +47,58 @@ Rectangle { } } - Rectangle { - id: inner + ColumnLayout { + id: columnLayout anchors.fill: parent - color: root.bgColor + spacing: 5 Button { id: openFile1Button - anchors { - top: parent.top - left: parent.left - right: exitButton.left - margins: d.margins - } - bgColor: "#212121" - bgColorSelected: "#757575" - textColorSelected: "white" - height: d.buttonHeight - text: (root.source1 == "") ? "Select file 1" : root.source1 + text: (VideoSingleton.source1 == '') ? qsTr("Select file 1") : VideoSingleton.source1 + Component.onCompleted: console.log("source1: " + VideoSingleton.source1) onClicked: { - fileBrowser.setFirstSource = true - fileBrowser.open() + fileDialog.setFirstSource = true + fileDialog.open() } + + Layout.fillWidth: true } Button { id: openFile2Button - anchors { - top: openFile1Button.bottom - left: parent.left - right: exitButton.left - margins: d.margins - } - bgColor: "#212121" - bgColorSelected: "#757575" - textColorSelected: "white" - height: d.buttonHeight - text: (root.source2 == "") ? "Select file 2" : root.source2 + text: (VideoSingleton.source2 == '') ? qsTr("Select file 2") : VideoSingleton.source2 + Component.onCompleted: console.log("source2: " + VideoSingleton.source2) onClicked: { - fileBrowser.setFirstSource = false - fileBrowser.open() + fileDialog.setFirstSource = false + fileDialog.open() } - } - Button { - id: exitButton - anchors { - top: parent.top - right: parent.right - margins: d.margins - } - bgColor: "#212121" - bgColorSelected: "#757575" - textColorSelected: "white" - width: parent.width / 10 - height: d.buttonHeight - text: "Exit" - onClicked: Qt.quit() + Layout.fillWidth: true } - Row { - id: modes - anchors.top: openFile2Button.bottom - anchors.margins: 0 - anchors.topMargin: 5 - Button { - width: root.width / 2 - height: 0.8 * d.itemHeight - bgColor: "#212121" - radius: 0 - text: "Video Modes" - enabled: false - } - Button { - width: root.width / 2 - height: 0.8 * d.itemHeight - bgColor: "#212121" - radius: 0 - text: "Camera Modes" - enabled: false + RowLayout { + Layout.fillWidth: true + + Label { + text: qsTr("Video Modes") + + horizontalAlignment: Qt.AlignHCenter + Layout.preferredWidth: 50 + Layout.fillWidth: true } - } + Label { + text: qsTr("Camera Modes") - Rectangle { - id: divider - height: 1 - width: parent.width - color: "black" - anchors.top: modes.bottom + horizontalAlignment: Qt.AlignHCenter + Layout.preferredWidth: 50 + Layout.fillWidth: true + } } SceneSelectionPanel { id: sceneSelectionPanel - itemHeight: d.itemHeight - color: "#212121" - anchors { - top: divider.bottom - left: parent.left - right: parent.right - bottom: parent.bottom - } + itemHeight: Math.min(width / 10, height / 10) + color: palette.dark radius: 0 onSceneSourceChanged: { sceneLoader.source = sceneSource @@ -162,16 +110,15 @@ Rectangle { } else { scene = sceneLoader.item if (scene) { - if (scene.contentType === "video" && source1 === "") { - errorDialog.show("You must first select a video file") + if (scene.contentType === "video" && VideoSingleton.source1 === "") { + errorDialog.show(qsTr("You must first select a video file")) sceneSource = "" } else { scene.parent = root - scene.color = root.bgColor - scene.buttonHeight = d.buttonHeight - scene.source1 = source1 - scene.source2 = source2 - scene.volume = volume + scene.color = root.palette.window + scene.source1 = VideoSingleton.source1 + scene.source2 = VideoSingleton.source2 + scene.volume = VideoSingleton.volume scene.anchors.fill = root scene.close.connect(closeScene) scene.content.initialize() @@ -180,8 +127,11 @@ Rectangle { } } videoFramePaintedConnection.target = scene - inner.visible = innerVisible + columnLayout.visible = innerVisible } + + Layout.fillWidth: true + Layout.fillHeight: true } } @@ -191,42 +141,46 @@ Rectangle { Connections { id: videoFramePaintedConnection + // qmllint disable function onVideoFramePainted() { if (performanceLoader.item) performanceLoader.item.videoFramePainted() } + // qmllint enable ignoreUnknownSignals: true } FileDialog { - id: fileBrowser + id: fileDialog property bool setFirstSource - onAccepted: { + onAccepted: function() { if (setFirstSource) - root.source1 = currentFile + VideoSingleton.source1 = selectedFile else - root.source2 = currentFile + VideoSingleton.source2 = selectedFile } } ErrorDialog { id: errorDialog anchors.fill: root - dialogWidth: d.itemHeight * 5 - dialogHeight: d.itemHeight * 3 + dialogWidth: Math.min(root.width, root.height) * 0.5 + dialogHeight: Math.min(root.width, root.height) * 0.3 enabled: false } // Called from main() once root properties have been set function init() { performanceLoader.init() - fileBrowser.currentFolder = videoPath + fileDialog.currentFolder = VideoSingleton.videoPath } + // qmllint disable function qmlFramePainted() { if (performanceLoader.item) performanceLoader.item.qmlFramePainted() } + // qmllint enable function closeScene() { sceneSelectionPanel.sceneSource = "" diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/Scene.qml b/examples/multimedia/video/qmlvideo/qmlvideo/Scene.qml index c2903f63d..e16478d41 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/Scene.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/Scene.qml @@ -2,11 +2,11 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls Rectangle { id: root - color: "black" - property alias buttonHeight: closeButton.height + color: palette.window property string source1 property string source2 property int contentWidth: parent.width / 2 @@ -24,13 +24,8 @@ Rectangle { right: parent.right margins: root.margins } - width: Math.max(parent.width, parent.height) / 12 - height: Math.min(parent.width, parent.height) / 12 z: 2.0 - bgColor: "#212121" - bgColorSelected: "#757575" - textColorSelected: "white" - text: "Back" + text: qsTr("Back") onClicked: root.close() } } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/SceneBasic.qml b/examples/multimedia/video/qmlvideo/qmlvideo/SceneBasic.qml index 69b3a9ef4..8ad6c99b8 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/SceneBasic.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/SceneBasic.qml @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls Scene { id: root @@ -21,15 +22,14 @@ Scene { onVideoFramePainted: root.videoFramePainted() } - Text { + Label { anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom margins: 20 } - text: content.started ? "Tap the screen to stop content" - : "Tap the screen to start content" - color: "#e0e0e0" + text: content.started ? qsTr("Tap the screen to stop content") + : qsTr("Tap the screen to start content") z: 2.0 } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/SceneFullScreen.qml b/examples/multimedia/video/qmlvideo/qmlvideo/SceneFullScreen.qml index 3e9997f37..ec8564311 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/SceneFullScreen.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/SceneFullScreen.qml @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls Scene { id: root @@ -19,8 +20,10 @@ Scene { states: [ State { name: "fullScreen" - PropertyChanges { target: content; width: content.parent.width } - PropertyChanges { target: content; height: content.parent.height } + PropertyChanges { + content.width: content.parent.width + content.height: content.parent.height + } } ] @@ -49,14 +52,13 @@ Scene { onVideoFramePainted: root.videoFramePainted() } - Text { + Label { anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom margins: 20 } - text: "Tap on the content to toggle full-screen mode" - color: "#e0e0e0" + text: qsTr("Tap on the content to toggle full-screen mode") z: 2.0 } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/SceneFullScreenInverted.qml b/examples/multimedia/video/qmlvideo/qmlvideo/SceneFullScreenInverted.qml index 837c440f9..cb96ac134 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/SceneFullScreenInverted.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/SceneFullScreenInverted.qml @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls Scene { id: root @@ -20,7 +21,7 @@ Scene { states: [ State { name: "nonFullScreen" - PropertyChanges { target: content; width: content.parent.contentWidth } + PropertyChanges { content.width: root.contentWidth } } ] @@ -43,7 +44,7 @@ Scene { MouseArea { anchors.fill: parent - onClicked: content.state = (content.state == "nonFullScreen") ? "baseState" : "nonFullScreen" + onClicked: content.state = (content.state === "nonFullScreen") ? "baseState" : "nonFullScreen" } onVideoFramePainted: root.videoFramePainted() @@ -54,14 +55,13 @@ Scene { } } - Text { + Label { anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom margins: 20 } - text: "Tap on the content to toggle full-screen mode" - color: "#e0e0e0" + text: qsTr("Tap on the content to toggle full-screen mode") z: 2.0 } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/SceneMove.qml b/examples/multimedia/video/qmlvideo/qmlvideo/SceneMove.qml index c8fe939d7..d1512831e 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/SceneMove.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/SceneMove.qml @@ -19,7 +19,7 @@ Scene { SequentialAnimation on x { id: animation loops: Animation.Infinite - property int from: margin + property int from: root.margin property int to: 100 property int duration: 1500 running: false diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/SceneMulti.qml b/examples/multimedia/video/qmlvideo/qmlvideo/SceneMulti.qml index 54571b055..f93dabcdd 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/SceneMulti.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/SceneMulti.qml @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls Scene { id: root @@ -24,28 +25,30 @@ Scene { id: root color: "transparent" - function content() { - return root.parent - } + signal start + signal stop - Text { + Label { anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom margins: 20 } - text: content() ? content().started ? "Tap to stop" : "Tap to start" : "" - color: "#e0e0e0" + // qmllint disable + text: root.started ? qsTr("Tap to stop") : qsTr("Tap to start") + // qmllint enable } MouseArea { anchors.fill: parent + // qmllint disable onClicked: { - if (content().started) - content().stop() + if (root.started) + root.stop() else - content().start() + root.start() } + // qmllint enable } } } @@ -63,14 +66,19 @@ Scene { showBorder: true showFrameRate: started source: parent.source1 - width: itemWidth + width: root.itemWidth volume: parent.volume Loader { id: video1StartStopLoader + + property bool started: parent.started + onLoaded: { item.parent = video1 item.anchors.fill = video1 + item.start.connect(video1.start) + item.stop.connect(video1.stop) } } @@ -79,17 +87,19 @@ Scene { Rectangle { id: cameraHolder + + property bool started: false + anchors { horizontalCenter: parent.horizontalCenter top: parent.top topMargin: root.itemTopMargin } border.width: 1 - border.color: "white" + border.color: palette.base color: "transparent" - width: itemWidth + width: root.itemWidth height: width - property bool started: false Loader { id: cameraLoader @@ -98,7 +108,7 @@ Scene { item.anchors.centerIn = cameraHolder item.contentType = "camera" item.showFrameRate = true - item.width = itemWidth + item.width = root.itemWidth item.z = 1.0 cameraErrorConnection.target = item item.initialize() @@ -107,17 +117,22 @@ Scene { Loader { id: cameraStartStopLoader + + property bool started: parent.started + sourceComponent: startStopComponent onLoaded: { item.parent = cameraHolder item.anchors.fill = cameraHolder item.z = 2.0 + item.start.connect(cameraHolder.start) + item.stop.connect(cameraHolder.stop) } } Connections { id: cameraErrorConnection - onError: { + function onError() { console.log("[qmlvideo] SceneMulti.camera.onError") cameraHolder.stop() } @@ -148,14 +163,19 @@ Scene { showBorder: true showFrameRate: started source: parent.source2 - width: itemWidth + width: root.itemWidth volume: parent.volume Loader { id: video2StartStopLoader + + property bool started: parent.started + onLoaded: { item.parent = video2 item.anchors.fill = video2 + item.start.connect(video2.start) + item.stop.connect(video2.stop) } } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/SceneOverlay.qml b/examples/multimedia/video/qmlvideo/qmlvideo/SceneOverlay.qml index 96c7af802..5863d618c 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/SceneOverlay.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/SceneOverlay.qml @@ -29,7 +29,7 @@ Scene { SequentialAnimation on x { id: xAnimation loops: Animation.Infinite - property int from: margin + property int from: root.margin property int to: 100 property int duration: 1500 running: false @@ -50,7 +50,7 @@ Scene { SequentialAnimation on y { id: yAnimation loops: Animation.Infinite - property int from: margin + property int from: root.margin property int to: 180 property int duration: 1500 running: false diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/SceneRotate.qml b/examples/multimedia/video/qmlvideo/qmlvideo/SceneRotate.qml index c38d4e1ce..1362522e6 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/SceneRotate.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/SceneRotate.qml @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls Scene { id: root @@ -26,10 +27,8 @@ Scene { bottom: rotateNegativeButton.top margins: parent.margins } - width: Math.max(parent.width, parent.height) / 10 - height: root.buttonHeight - text: "Rotate +" + delta - onClicked: content.rotation = content.rotation + delta + text: qsTr("Rotate +%1").arg(root.delta) + onClicked: content.rotation = content.rotation + root.delta } Button { @@ -39,10 +38,8 @@ Scene { verticalCenter: parent.verticalCenter margins: parent.margins } - width: Math.max(parent.width, parent.height) / 10 - height: root.buttonHeight - text: "Rotate -" + delta - onClicked: content.rotation = content.rotation - delta + text: qsTr("Rotate -%1").arg(root.delta) + onClicked: content.rotation = content.rotation - root.delta } Button { @@ -52,8 +49,6 @@ Scene { verticalCenter: parent.verticalCenter margins: parent.margins } - width: Math.max(parent.width, parent.height) / 25 - height: root.buttonHeight enabled: false text: content.rotation % 360 } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/SceneSelectionPanel.qml b/examples/multimedia/video/qmlvideo/qmlvideo/SceneSelectionPanel.qml index 0bced4372..0301f5452 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/SceneSelectionPanel.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/SceneSelectionPanel.qml @@ -2,6 +2,9 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls + +pragma ComponentBehavior: Bound Rectangle { id: root @@ -10,48 +13,51 @@ Rectangle { ListModel { id: videolist - ListElement { name: "Multi"; source: "SceneMulti.qml" } - ListElement { name: "Video"; source: "VideoBasic.qml" } - ListElement { name: "Drag"; source: "VideoDrag.qml" } - ListElement { name: "Fillmode"; source: "VideoFillMode.qml" } - ListElement { name: "Fullscreen"; source: "VideoFullScreen.qml" } - ListElement { name: "Fullscreen-inverted"; source: "VideoFullScreenInverted.qml" } - ListElement { name: "Metadata"; source: "VideoMetadata.qml" } - ListElement { name: "Move"; source: "VideoMove.qml" } - ListElement { name: "Overlay"; source: "VideoOverlay.qml" } - ListElement { name: "Playback Rate"; source: "VideoPlaybackRate.qml" } - ListElement { name: "Resize"; source: "VideoResize.qml" } - ListElement { name: "Rotate"; source: "VideoRotate.qml" } - ListElement { name: "Spin"; source: "VideoSpin.qml" } - ListElement { name: "Seek"; source: "VideoSeek.qml" } + ListElement { name: qsTr("Multi"); source: "SceneMulti.qml" } + ListElement { name: qsTr("Video"); source: "VideoBasic.qml" } + ListElement { name: qsTr("Drag"); source: "VideoDrag.qml" } + ListElement { name: qsTr("Fillmode"); source: "VideoFillMode.qml" } + ListElement { name: qsTr("Fullscreen"); source: "VideoFullScreen.qml" } + ListElement { name: qsTr("Fullscreen-inverted"); source: "VideoFullScreenInverted.qml" } + ListElement { name: qsTr("Metadata"); source: "VideoMetadata.qml" } + ListElement { name: qsTr("Move"); source: "VideoMove.qml" } + ListElement { name: qsTr("Overlay"); source: "VideoOverlay.qml" } + ListElement { name: qsTr("Playback Rate"); source: "VideoPlaybackRate.qml" } + ListElement { name: qsTr("Resize"); source: "VideoResize.qml" } + ListElement { name: qsTr("Rotate"); source: "VideoRotate.qml" } + ListElement { name: qsTr("Spin"); source: "VideoSpin.qml" } + ListElement { name: qsTr("Seek"); source: "VideoSeek.qml" } } ListModel { id: cameralist - ListElement { name: "Camera"; source: "CameraBasic.qml" } - ListElement { name: "Drag"; source: "CameraDrag.qml" } - ListElement { name: "Fullscreen"; source: "CameraFullScreen.qml" } - ListElement { name: "Fullscreen-inverted"; source: "CameraFullScreenInverted.qml" } - ListElement { name: "Move"; source: "CameraMove.qml" } - ListElement { name: "Overlay"; source: "CameraOverlay.qml" } - ListElement { name: "Resize"; source: "CameraResize.qml" } - ListElement { name: "Rotate"; source: "CameraRotate.qml" } - ListElement { name: "Spin"; source: "CameraSpin.qml" } + ListElement { name: qsTr("Camera"); source: "CameraBasic.qml" } + ListElement { name: qsTr("Drag"); source: "CameraDrag.qml" } + ListElement { name: qsTr("Fullscreen"); source: "CameraFullScreen.qml" } + ListElement { name: qsTr("Fullscreen-inverted"); source: "CameraFullScreenInverted.qml" } + ListElement { name: qsTr("Move"); source: "CameraMove.qml" } + ListElement { name: qsTr("Overlay"); source: "CameraOverlay.qml" } + ListElement { name: qsTr("Resize"); source: "CameraResize.qml" } + ListElement { name: qsTr("Rotate"); source: "CameraRotate.qml" } + ListElement { name: qsTr("Spin"); source: "CameraSpin.qml" } } Component { id: leftDelegate Item { width: root.width / 2 - height: 0.8 * itemHeight + height: 0.8 * root.itemHeight + + required property string name + required property string source Button { anchors.fill: parent anchors.margins: 5 anchors.rightMargin: 2.5 anchors.bottomMargin: 0 - text: name - onClicked: root.sceneSource = source + text: parent.name + onClicked: root.sceneSource = parent.source } } } @@ -60,22 +66,25 @@ Rectangle { id: rightDelegate Item { width: root.width / 2 - height: 0.8 * itemHeight + height: 0.8 * root.itemHeight + + required property string name + required property string source Button { anchors.fill: parent anchors.margins: 5 anchors.leftMargin: 2.5 anchors.bottomMargin: 0 - text: name - onClicked: root.sceneSource = source + text: parent.name + onClicked: root.sceneSource = parent.source } } } Flickable { anchors.fill: parent - contentHeight: (itemHeight * videolist.count) + 10 + contentHeight: (root.itemHeight * videolist.count) + 10 clip: true Row { diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/SeekControl.qml b/examples/multimedia/video/qmlvideo/qmlvideo/SeekControl.qml index 392f8afb2..646e5e8ef 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/SeekControl.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/SeekControl.qml @@ -15,7 +15,7 @@ Item { Rectangle { id: background anchors.fill: parent - color: "white" + color: palette.base opacity: 0.3 radius: parent.height / 15 } @@ -24,7 +24,7 @@ Item { id: progressBar anchors { left: parent.left; top: parent.top; bottom: parent.bottom } width: seekControl.duration == 0 ? 0 : background.width * seekControl.playPosition / seekControl.duration - color: "black" + color: palette.highlight opacity: 0.7 } @@ -33,9 +33,9 @@ Item { anchors { left: parent.left; top: parent.top; bottom: parent.bottom; leftMargin: 10 } horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter - color: "white" + color: palette.windowText smooth: true - text: formatTime(playPosition) + text: seekControl.formatTime(seekControl.playPosition) } Text { @@ -43,16 +43,16 @@ Item { anchors { right: parent.right; top: parent.top; bottom: parent.bottom; rightMargin: 10 } horizontalAlignment: Text.AlignRight verticalAlignment: Text.AlignVCenter - color: "white" + color: palette.windowText smooth: true - text: formatTime(duration) + text: seekControl.formatTime(seekControl.duration) } Rectangle { id: progressHandle height: parent.height width: parent.height / 2 - color: "white" + color: palette.accent opacity: 0.5 anchors.verticalCenter: progressBar.verticalCenter x: seekControl.duration == 0 ? 0 : seekControl.playPosition / seekControl.duration * background.width @@ -96,8 +96,8 @@ Item { function formatTime(timeInMs) { if (!timeInMs || timeInMs <= 0) return "0:00" - var seconds = timeInMs / 1000; - var minutes = Math.floor(seconds / 60) + let seconds = timeInMs / 1000; + let minutes = Math.floor(seconds / 60) seconds = Math.floor(seconds % 60) if (seconds < 10) seconds = "0" + seconds; return minutes + ":" + seconds diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoBasic.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoBasic.qml index 83ef7cb6b..15c25c978 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoBasic.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoBasic.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneBasic { contentType: "video" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoDrag.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoDrag.qml index ab0502e7c..4a5c5d49b 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoDrag.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoDrag.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneDrag { contentType: "video" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoDummy.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoDummy.qml index addc5bc3e..a30b9ebf6 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoDummy.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoDummy.qml @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls // Item which is loaded by VideoItem if Qt Multimedia is not available Rectangle { @@ -18,12 +19,11 @@ Rectangle { signal sizeChanged signal framePainted - Text { + Label { anchors.fill: parent anchors.margins: 10 - color: "white" horizontalAlignment: Text.AlignHCenter - text: "Failed to create Video item\n\nCheck that Qt Multimedia is installed" + text: qsTr("Failed to create Video item\n\nCheck that Qt Multimedia is installed") verticalAlignment: Text.AlignVCenter wrapMode: Text.Wrap } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoFillMode.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoFillMode.qml index 86216d17f..af950c735 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoFillMode.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoFillMode.qml @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls import QtMultimedia Scene { @@ -24,24 +25,24 @@ Scene { verticalCenter: parent.verticalCenter margins: parent.margins } - width: Math.max(parent.width, parent.height) / 5 - height: root.buttonHeight - text: "PreserveAspectFit" + text: qsTr("PreserveAspectFit") + // qmllint disable onClicked: { if (!content.dummy) { - var video = content.contentItem() + let video = content.contentItem if (video.fillMode === VideoOutput.Stretch) { video.fillMode = VideoOutput.PreserveAspectFit - text = "PreserveAspectFit" + text = qsTr("PreserveAspectFit") } else if (video.fillMode === VideoOutput.PreserveAspectFit) { video.fillMode = VideoOutput.PreserveAspectCrop - text = "PreserveAspectCrop" + text = qsTr("PreserveAspectCrop") } else { video.fillMode = VideoOutput.Stretch - text = "Stretch" + text = qsTr("Stretch") } } } + // qmllint enable } Component.onCompleted: root.content = content diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoFullScreen.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoFullScreen.qml index 1fec029a9..e49faadb6 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoFullScreen.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoFullScreen.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneFullScreen { contentType: "video" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoFullScreenInverted.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoFullScreenInverted.qml index 0ff5037ec..0bf82941e 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoFullScreenInverted.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoFullScreenInverted.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneFullScreenInverted { contentType: "video" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoMetadata.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoMetadata.qml index d9b529607..f83cbffe9 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoMetadata.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoMetadata.qml @@ -2,14 +2,17 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls import QtMultimedia +pragma ComponentBehavior: Bound + Scene { id: root property string contentType: "video" Content { - id: content + id: videoContent anchors.centerIn: parent width: parent.contentWidth contentType: "video" @@ -26,61 +29,52 @@ Scene { id: metadata Column { anchors.fill: parent - property var videoMetaData: content.contentItem().metaData - Text { - color: "#e0e0e0" - text: "Title:" + videoMetaData.value(MediaMetaData.Title) + // qmllint disable + property var videoMetaData: videoContent.contentItem?.metaData + // qmllint enable + Label { + text: qsTr("Title: %1").arg(parent.videoMetaData?.value(MediaMetaData.Title) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Resolution:" + videoMetaData.value(MediaMetaData.Resolution) + Label { + text: qsTr("Resolution: %1").arg(parent.videoMetaData?.value(MediaMetaData.Resolution) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Media type:" + videoMetaData.value(MediaMetaData.MediaType) + Label { + text: qsTr("Media type: %1").arg(parent.videoMetaData?.value(MediaMetaData.MediaType) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Video codec:" + videoMetaData.value(MediaMetaData.VideoCodec) + Label { + text: qsTr("Video codec: %1").arg(parent.videoMetaData?.value(MediaMetaData.VideoCodec) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Video bit rate:" + videoMetaData.value(MediaMetaData.VideoBitRate) + Label { + text: qsTr("Video bit rate: %1").arg(parent.videoMetaData?.value(MediaMetaData.VideoBitRate) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Video frame rate:" +videoMetaData.value(MediaMetaData.VideoFrameRate) + Label { + text: qsTr("Video frame rate: %1").arg(parent.videoMetaData?.value(MediaMetaData.VideoFrameRate) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Audio codec:" + videoMetaData.value(MediaMetaData.AudioCodec) + Label { + text: qsTr("Audio codec: %1").arg(parent.videoMetaData?.value(MediaMetaData.AudioCodec) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Audio bit rate:" + videoMetaData.value(MediaMetaData.AudioBitRate) + Label { + text: qsTr("Audio bit rate: %1").arg(parent.videoMetaData?.value(MediaMetaData.AudioBitRate) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Date:" + videoMetaData.value(MediaMetaData.Date) + Label { + text: qsTr("Date: %1").arg(parent.videoMetaData?.value(MediaMetaData.Date) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Description:" + videoMetaData.value(MediaMetaData.Description) + Label { + text: qsTr("Description: %1").arg(parent.videoMetaData?.value(MediaMetaData.Description) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Copyright:" + videoMetaData.value(MediaMetaData.Copyright) + Label { + text: qsTr("Copyright: %1").arg(parent.videoMetaData?.value(MediaMetaData.Copyright) ?? qsTr("Unknown")) } - Text { - color: "#e0e0e0" - text: "Seekable:" + content.contentItem().seekable + Label { + // qmllint disable + text: qsTr("Seekable: %1").arg(videoContent.contentItem?.seekable ?? qsTr("Unknown")) + // qmllint enable } - Text { - color: "#e0e0e0" - text: "Orientation:" + videoMetaData.value(MediaMetaData.Orientation) + Label { + text: qsTr("Orientation: %1").arg(parent.videoMetaData?.value(MediaMetaData.Orientation) ?? qsTr("Unknown")) } } } - Component.onCompleted: root.content = content + Component.onCompleted: root.content = videoContent } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoMove.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoMove.qml index abfa32b25..2b9230f3c 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoMove.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoMove.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneMove { contentType: "video" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoOverlay.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoOverlay.qml index e664c36d6..576b33ff9 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoOverlay.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoOverlay.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneOverlay { contentType: "video" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoPlaybackRate.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoPlaybackRate.qml index 614dcd424..55e38ef19 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoPlaybackRate.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoPlaybackRate.qml @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause import QtQuick +import QtQuick.Controls Scene { id: root @@ -26,12 +27,10 @@ Scene { bottom: decreaseButton.top margins: parent.margins } - width: Math.max(parent.width, parent.height) / 10 - height: root.buttonHeight - text: "Increase" + text: qsTr("Increase") onClicked: { - var video = content.contentItem() - video.playbackRate += delta + let video = (content.contentItem as VideoItem) + video.playbackRate += root.delta } } @@ -42,12 +41,10 @@ Scene { verticalCenter: parent.verticalCenter margins: parent.margins } - width: Math.max(parent.width, parent.height) / 10 - height: root.buttonHeight - text: "Decrease" + text: qsTr("Decrease") onClicked: { - var video = content.contentItem() - video.playbackRate -= delta + let video = (content.contentItem as VideoItem) + video.playbackRate -= root.delta } } @@ -58,10 +55,10 @@ Scene { verticalCenter: parent.verticalCenter margins: parent.margins } - width: Math.max(parent.width, parent.height) / 25 - height: root.buttonHeight enabled: false - text: Math.round(10 * content.contentItem().playbackRate) / 10 + // qmllint disable + text: Math.round(10 * content.contentItem?.playbackRate ?? 1) / 10 + // qmllint enable } Component.onCompleted: root.content = content diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoResize.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoResize.qml index a530d96b7..88fe7a2d2 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoResize.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoResize.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneResize { contentType: "video" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoRotate.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoRotate.qml index ec74a55ea..d429ec413 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoRotate.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoRotate.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneRotate { contentType: "video" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoSeek.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoSeek.qml index 3c16ddd70..5e2584fb6 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoSeek.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoSeek.qml @@ -25,9 +25,11 @@ Scene { margins: 10 bottom: parent.bottom } - duration: content.contentItem() ? content.contentItem().duration : 0 - playPosition: content.contentItem() ? content.contentItem().position : 0 - onSeekPositionChanged: content.contentItem().seek(seekPosition); + // qmllint disable + duration: content.contentItem?.duration ?? 0 + playPosition: content.contentItem?.position ?? 0 + onSeekPositionChanged: content.contentItem?.seek(seekPosition); + // qmllint enable } Component.onCompleted: root.content = content diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/VideoSpin.qml b/examples/multimedia/video/qmlvideo/qmlvideo/VideoSpin.qml index f6ba42d0e..7c365ddc7 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/VideoSpin.qml +++ b/examples/multimedia/video/qmlvideo/qmlvideo/VideoSpin.qml @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -import QtQuick - SceneSpin { contentType: "video" } diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/qmldir b/examples/multimedia/video/qmlvideo/qmlvideo/qmldir index a43cb40ba..1cba13d95 100644 --- a/examples/multimedia/video/qmlvideo/qmlvideo/qmldir +++ b/examples/multimedia/video/qmlvideo/qmlvideo/qmldir @@ -1,6 +1,5 @@ module qmlvideo -Button 1.0 Button.qml CameraBasic 1.0 CameraBasic.qml CameraDrag 1.0 CameraDrag.qml CameraDummy 1.0 CameraDummy.qml diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/qmlvideo_global.h b/examples/multimedia/video/qmlvideo/qmlvideo/qmlvideo_global.h new file mode 100644 index 000000000..8df5b5b64 --- /dev/null +++ b/examples/multimedia/video/qmlvideo/qmlvideo/qmlvideo_global.h @@ -0,0 +1,10 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QtCore/QtGlobal> + +#if defined(QMLVIDEO_LIB) +#define QMLVIDEO_LIB_EXPORT Q_DECL_EXPORT +#else +#define QMLVIDEO_LIB_EXPORT Q_DECL_IMPORT +#endif diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/videosingleton.cpp b/examples/multimedia/video/qmlvideo/qmlvideo/videosingleton.cpp new file mode 100644 index 000000000..2b02fa505 --- /dev/null +++ b/examples/multimedia/video/qmlvideo/qmlvideo/videosingleton.cpp @@ -0,0 +1,54 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "videosingleton.h" + +VideoSingleton::VideoSingleton(QObject * parent) : QObject(parent) +{ } + +QUrl VideoSingleton::source1() const +{ + return m_source1; +} +void VideoSingleton::setSource1(const QUrl &source1) +{ + if (source1 == m_source1) + return; + m_source1 = source1; + emit source1Changed(); +} +QUrl VideoSingleton::source2() const +{ + return m_source2; +} +void VideoSingleton::setSource2(const QUrl &source2) +{ + if (source2 == m_source2) + return; + m_source2 = source2; + emit source2Changed(); +} +qreal VideoSingleton::volume() const +{ + return m_volume; +} +void VideoSingleton::setVolume(qreal volume) +{ + if (volume == m_volume) + return; + m_volume = volume; + emit volumeChanged(); +} +QUrl VideoSingleton::videoPath() const +{ + return m_videoPath; +} +void VideoSingleton::setVideoPath(const QUrl &videoPath) +{ + if (m_videoPath == videoPath) + return; + m_videoPath = videoPath; + emit videoPathChanged(); +} + +#include "moc_videosingleton.cpp" diff --git a/examples/multimedia/video/qmlvideo/qmlvideo/videosingleton.h b/examples/multimedia/video/qmlvideo/qmlvideo/videosingleton.h new file mode 100644 index 000000000..3e0d56247 --- /dev/null +++ b/examples/multimedia/video/qmlvideo/qmlvideo/videosingleton.h @@ -0,0 +1,48 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef QMLVIDEOSINGLETON_H +#define QMLVIDEOSINGLETON_H + +#include "qmlvideo_global.h" + +#include <QtQml/qqml.h> + +class QMLVIDEO_LIB_EXPORT VideoSingleton : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUrl source1 READ source1 WRITE setSource1 NOTIFY source1Changed FINAL) + Q_PROPERTY(QUrl source2 READ source2 WRITE setSource2 NOTIFY source2Changed FINAL) + Q_PROPERTY(QUrl videoPath READ videoPath WRITE setVideoPath NOTIFY videoPathChanged FINAL) + Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged FINAL) + QML_SINGLETON + QML_ELEMENT + +public: + explicit VideoSingleton(QObject *parent = nullptr); + + QUrl source1() const; + void setSource1(const QUrl &source1); + QUrl source2() const; + void setSource2(const QUrl &source2); + QUrl videoPath() const; + void setVideoPath(const QUrl &videoPath); + qreal volume() const; + void setVolume(qreal volume); + +Q_SIGNALS: + void source1Changed(); + void source2Changed(); + void volumeChanged(); + void videoPathChanged(); + +private: + QUrl m_source1; + QUrl m_source2; + QUrl m_videoPath; + qreal m_volume = 0.5; +}; + +QML_DECLARE_TYPE(VideoSingleton); + +#endif // QMLVIDEOSINGLETON_H |