Index: leahi.qrc =================================================================== diff -u -r85acfb989e40d697550f788b85a1d287b3316728 -r0f7ff0b328197a1737bd33cde56bac95fa98e1eb --- leahi.qrc (.../leahi.qrc) (revision 85acfb989e40d697550f788b85a1d287b3316728) +++ leahi.qrc (.../leahi.qrc) (revision 0f7ff0b328197a1737bd33cde56bac95fa98e1eb) @@ -134,6 +134,10 @@ sources/gui/qml/components/SliderArrows.qml sources/gui/qml/components/QRCode.qml sources/gui/qml/components/VideoScreen.qml + sources/gui/qml/components/AnimationScreen.qml + sources/gui/qml/components/ImageAnimator.qml + sources/gui/qml/components/ImageNameLoader.qml + sources/gui/qml/components/PlaybackController.qml sources/gui/qml/compounds/PressureRangeSlider.qml Index: sources/gui/qml/components/AnimationScreen.qml =================================================================== diff -u --- sources/gui/qml/components/AnimationScreen.qml (revision 0) +++ sources/gui/qml/components/AnimationScreen.qml (revision 0f7ff0b328197a1737bd33cde56bac95fa98e1eb) @@ -0,0 +1,158 @@ +/*! + * + * Copyright (c) 2021-2024 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file AnimationScreen.qml + * \author (last) Behrouz NematiPour + * \date (last) 24-02-2025 + * \author (original) Behrouz NematiPour + * \date (original) 24-02-2025 + * + */ + +// Qt +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import Qt.labs.folderlistmodel 2.8 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" + + +/*! + * \brief Contains a back button as well + * as the current progress in each of the steps. + */ +ScreenItem { + id: _root + + visible : true; + backgroundRect.width : parent.width; + backgroundRect.height : parent.height; + backgroundRect.color : Colors.transparent; + + property string path : "file:///home/denali/animation/"; + property var nameList : _nameListLoader.nameList; + + readonly property int frameWidth : parent.width - 40; + readonly property int frameHeight : parent.height - 120; + readonly property int frameTopMargin : 100; + readonly property int frameLeftMargin : 20; + readonly property int frameRatius : Variables.dialogRadius; + + ImageNameLoader { + id: _nameListLoader + + path : _root.path; + + anchors { + top : _root.top; + topMargin : 10; + horizontalCenter: _root.horizontalCenter; + } + + Connections { + target: _nameListLoader + + function onNamesLoaded() { + _playController.playListReady(_root.nameList.length); + _imgAnimator.playListReady(_root.nameList); + _waitingMsg.visible = false; + } + } + } + + ImageAnimator { + id: _imgAnimator + path: _root.path; + + width : _root.frameWidth; + height: _root.frameHeight; + radius: _root.frameRatius; + + anchors { + left : _root.left; + top : _root.top; + leftMargin : _root.frameLeftMargin; + topMargin : _root.frameTopMargin; + } + + Connections { + target: _imgAnimator + + function onNextImageLoaded(nameIdx) { + _nameListLoader.showNextName(nameIdx); + } + + function onImageAnimatorDone() { + _playController.reset(); + _nameListLoader.reset(); + } + + function onEnableForward(bValue) { + _playController.enableForwardBtn(bValue); + } + + function onEnableBackward(bValue){ + _playController.enableBackwardBtn(bValue); + } + } + } + + PlaybackController { id: _playController + anchors.horizontalCenter: _imgAnimator.horizontalCenter + anchors.bottom : _imgAnimator.bottom; + anchors.bottomMargin : 10; + width : 800; //Variables.playbackControllerHeight; + height : 300; //Variables.playbackControllerHeight; + radius : Variables.dialogRadius; + color : Colors.transparent; + + Connections { + target: _playController; + + function onResumeClicked() { + _imgAnimator.startPlay(); + } + + function onPauseClicked() { + _imgAnimator.pausePlay(); + } + + function onForewardClicked() { + _imgAnimator.foreward(); + } + + function onBackwardClicked() { + _imgAnimator.backward(); + } + } + } + + + Rectangle { + id: _waitingMsg; + anchors.centerIn: parent; + width : 600; + height : 200; + radius : 4; + color : "lightyellow"; + border.width: 4; + border.color: "white"; + + Text { + anchors.centerIn: parent; + font.bold: true; + text: "Please Wait ..." + } + } + + Component.onCompleted: { + _waitingMsg.visible = true; + } +} Index: sources/gui/qml/components/ImageAnimator.qml =================================================================== diff -u --- sources/gui/qml/components/ImageAnimator.qml (revision 0) +++ sources/gui/qml/components/ImageAnimator.qml (revision 0f7ff0b328197a1737bd33cde56bac95fa98e1eb) @@ -0,0 +1,221 @@ + +/*! + * + * Copyright (c) 2021-2024 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file AnimationScreen.qml + * \author (last) Behrouz NematiPour + * \date (last) 24-02-2025 + * \author (original) Behrouz NematiPour + * \date (original) 24-02-2025 + * + */ + +// Qt +import QtQuick 2.12 +import QtQuick.Controls 2.12 +// swipeview +import Qt.labs.folderlistmodel 2.8 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" + + +/*! + * \brief Contains a back button as well + * as the current progress in each of the steps. + */ +Rectangle { + id: _root + + signal imageAnimatorDone(); + signal nextImageLoaded (int nameIdx); + signal enableForward (bool bValue); + signal enableBackward (bool bValue); + + property var nameList : []; + property int nameIdx : 0; + property int animationInterval : 3000; // Variables.imageAnimationInterval; + property string path : "" + + property int boarderWidth : Variables.borderWidth; + property string boarderColor : Colors.borderButton + property int imgWidth : _root.width - 10; + property int imgHeight : _root.height - 10; + + color : Colors.transparent + border.width: _root.boarderWidth; + border.color: _root.boarderColor; + + onVisibleChanged: { + if(!visible) { + resetAnimation(); + } + } + + function resetAnimation() { + _animationTimer.stop(); + + if(_imageView.currentIndex >= 0) { + _imageView.model.remove(_imageView.currentIndex); + } + + nameIdx = 0; + nextImageLoaded(nameIdx); + + imageAnimatorDone(); + + enableBackward(false); + enableForward(true); + } + + function playListReady(names) { + nameList = names; + } + + function startPlay() { + if(nameIdx >= nameList.length) { + nameIdx = 0; + } + + _animationTimer.start(); + } + + function pausePlay() { + _animationTimer.stop(); + } + + function foreward() { + if(nameIdx >= nameList.length) { + enableForward(false); + return; + } + + if( (nameIdx > 0) && (nameIdx < nameList.length) ) { + _imageView.model.remove(_imageView.currentIndex); + } + + _imageView.model.insert(0, { "name": nameList[nameIdx]}); + nextImageLoaded(nameIdx); + nameIdx++; + + sendAnimationState(); + } + + function backward() { + if(nameIdx <= 0) { + enableBackward(false); + return; + } + + nameIdx--; + _imageView.model.remove(_imageView.currentIndex); + _imageView.model.insert(0, { "name": nameList[nameIdx]}); + nextImageLoaded(nameIdx); + enableForward(true); + } + + function sendAnimationState() { + if(nameIdx >= nameList.length) { + enableForward(false); + } + else { + enableForward(true); + } + + if(nameIdx < 1) { + enableBackward(false); + } + else { + enableBackward(true); + } + } + + ListView { + id: _imageView + property alias _model: _imageView.model; + + anchors { + fill: _root; + } + + model : ListModel {} + interactive : false; + highlightRangeMode : ListView.StrictlyEnforceRange; + snapMode : ListView.SnapToItem; + clip : true; + focus : true; + + delegate: Rectangle { + width : _root.imgWidth; + height : _root.imgHeight; + radius : 6; + color : "darkblue"; + Image { + anchors.fill: parent; + source : path + name; + } + } + + add: Transition { + NumberAnimation { + property: "opacity"; + from : 0.5; + to : 1; + duration: 600; + } + NumberAnimation { + property: "scale"; + from : 0.6; + to : 0.9; + duration: 500; + } + } + + remove: Transition { + NumberAnimation { + property: "scale"; + to : 0; + duration: 600; + } + } + + + MouseArea { + anchors.fill: parent; + onClicked: { + _playController.showButtonsHandler(); + } + } + + Timer { + id: _animationTimer + interval: animationInterval; + running : false; + repeat : true; + onTriggered: { + if(nameIdx >= nameList.length) { + running = false; + imageAnimatorDone(); + return; + } + + if( ((nameIdx > 0) && (nameIdx < nameList.length)) || (_imageView.currentIndex >= 0)) { + _imageView.model.remove(_imageView.currentIndex); + } + + _imageView.model.insert(0, { "name": nameList[nameIdx]}) + nextImageLoaded(nameIdx); + + nameIdx++; + + sendAnimationState(); + } + } + } +} Index: sources/gui/qml/components/ImageNameLoader.qml =================================================================== diff -u --- sources/gui/qml/components/ImageNameLoader.qml (revision 0) +++ sources/gui/qml/components/ImageNameLoader.qml (revision 0f7ff0b328197a1737bd33cde56bac95fa98e1eb) @@ -0,0 +1,131 @@ +/*! + * + * Copyright (c) 2021-2024 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file ImageNames.qml + * \author (last) Behrouz NematiPour + * \date (last) 24-02-2025 + * \author (original) Behrouz NematiPour + * \date (original) 24-02-2025 + * + */ + +// Qt +import QtQuick 2.12 +import QtQuick.Controls 2.12 // swipeview +import Qt.labs.folderlistmodel 2.8 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" + +/*! + * \brief Contains a back button as well + * as the current progress in each of the steps. + */ +Rectangle { id: _root + + signal namesLoaded() + property string path : ""; + property string fileType : "*.png"; + property var nameList : []; + property int numOfFiles : _nameModel.count; + property alias mouseEnabled: _nameViewBtn.enabled; + + function reset() { + _nameView.currentIndex = 0; + } + + function addIt(txt) { + nameList.push(txt); + } + + function showNextName(nameIdx) { + if(!_nameView.highlightFollowsCurrentItem) { + _nameView.highlightFollowsCurrentItem = true; + } + _nameView.currentIndex = nameIdx; + } + + function loadImageNames() { + for(var i = _nameView.currentIndex; i < numOfFiles; i++) { + _nameView.currentIndex = i; + } + + _root.border.width = Variables.dialogRadius; + _root.border.color = "white"; + _nameView.visible = true; + _nameViewBtn.enabled = true; + } + + width : 410; + height : 60; + radius : 4; + color : "transparent"; + + ListView { id: _nameView + visible : false; + anchors.centerIn: parent; + width : 400; + height : 50; + model : _nameModel; + delegate : _nameDelegate; + clip : true; + focus : true; + highlight : highlight; + highlightFollowsCurrentItem: false; + + Component { id: _nameDelegate + + Rectangle { id: _rect + width: 400; + height: 50; + color: "darkblue"; + radius: 5; + Text { id: _txt + anchors.centerIn: parent; + color : "white"; + text : model.fileName; + + onTextChanged : { + if(_nameView.count > nameList.length) { + addIt(text); + } + } + } + } + } + + FolderListModel { id: _nameModel + folder : _root.path; + nameFilters : [ _root.fileType ]; + } + + MouseArea { id: _nameViewBtn + enabled : false; + anchors.fill: parent; + onClicked: { + } + } + } + + Timer { + id: _timer + interval: 3000; + running : true; + repeat : false; + onTriggered: { + loadImageNames(); + namesLoaded(); + } + } + + Component.onCompleted: { + _timer.start(); + } +} + Index: sources/gui/qml/components/PlaybackController.qml =================================================================== diff -u --- sources/gui/qml/components/PlaybackController.qml (revision 0) +++ sources/gui/qml/components/PlaybackController.qml (revision 0f7ff0b328197a1737bd33cde56bac95fa98e1eb) @@ -0,0 +1,200 @@ +/*! + * + * Copyright (c) 2019-2025 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file VideoScreen.qml + * \author (last) Behrouz NematiPour + * \date (last) 2-Feb-2025 + * \author (original) Behrouz NematiPour + * \date (original) 2-Feb-2025 + * + */ + +// Qt +import QtQuick 2.12 +import QtMultimedia 5.9 + +// Qml imports +import "qrc:/globals" +import "qrc:/components" + +Rectangle { id: _root + + property bool showButtons : false; + property int showButtonsTimeOut : 5000; // ms // Variables.playbackCtrlBtnTimeOut; + property int transitionInterval : 300; // ms + property int stepsInterval : 4000; // ms // Variables.playbackCtrlStepInterval + + signal resumeClicked (); + signal pauseClicked (); + signal backwardClicked(); + signal forewardClicked(); + + + function playListReady(numOfNames) { + _backwardBtn.enabled = false; + + if(numOfNames > 0) { + _forwardBtn.enabled = true; + } + + showButtonsHandler(); + } + + function reset() { + _forwardBtn.enabled = false; + _backwardBtn.enabled = true; + + _pauseBtn.visible = false + _resumeBtn.visible = !_pauseBtn.visible + } + + // Video Play Controller + function resumeBtnClicked() { + _resumeBtn.visible = false + _pauseBtn.visible = !_resumeBtn.visible + _root.resumeClicked(); + } + + function pauseBtnClicked() { + _pauseBtn.visible = false + _resumeBtn.visible = !_pauseBtn.visible + _root.pauseClicked(); + } + + function _backwardBtnClicked() { + _root.backwardClicked(); + } + + function forwardBtnClicked() { + _root.forewardClicked(); + } + + function enableForewardBtn(bValue) { + _forwardBtn.enabled = bValue + } + + function enableBackwardBtn(bValue) { + _backwardBtn.enabled = bValue + } + + + function showButtonsHandler() { + showButtons = true + _singleShotTimer.restart() + } + + // Page Event Handler + onVisibleChanged: { + if(!visible) { + //actions before exiting the screen + _singleShotTimer.stop() + } + } + + MouseArea { id: _playArea + anchors.fill: parent + onPressed: { + showButtonsHandler(); + } + } + + Timer { id: _singleShotTimer + interval: showButtonsTimeOut + running : false + repeat : false + onTriggered: { + showButtons = false + _singleShotTimer.stop() + } + } + + // State handler for dynamically show/hide the video control buttons with transition + states: [ + State { + name: "showButtons" + when: showButtons + PropertyChanges { + target: _buttonRow + opacity: 100 + } + }, + + State { + name: "hideButtons" + when: !showButtons + PropertyChanges { + target: _buttonRow + opacity: 0 + } + } + ] + + transitions: Transition { id: _transition + SequentialAnimation { + OpacityAnimator { + duration: transitionInterval + } + } + } + + // Video Control Buttons + Row { id: _buttonRow + opacity: 0 + enabled: showButtons + spacing: 175 + anchors { + horizontalCenter: _root.horizontalCenter + bottom: _root.bottom + bottomMargin: 110 // Variables.notificationHeight + 55 // + the texts height + } + + ImageText { + id: _backwardBtn + visible: true + anchors.bottom: _buttonRow.bottom + diameter: 85; //Variables.playbackCtlIconDiameter + source: "qrc:/images/iBackward" + text: qsTr("Backward") + fontSize: 26; //Fonts.fontPixelplaybackCtlButton + onClicked: _backwardBtnClicked() + } + + ImageText { + id: _resumeBtn + visible: true + enabled: true + anchors.bottom: _buttonRow.bottom + diameter: 110; //Variables.playbackCtlIconDiameterResumePause + source: "qrc:/images/iResume" + text: qsTr("Resume") + fontSize: 26; //Fonts.fontPixelplaybackCtlButton + onClicked: resumeBtnClicked() + } + + ImageText { + id: _pauseBtn + visible: !_resumeBtn.visible + anchors.bottom: _buttonRow.bottom + diameter: 110; //Variables.playbackCtlIconDiameterResumePause + source: "qrc:/images/iPauseLightBlue" + text: qsTr("Pause") + fontSize: 26; //Fonts.fontPixelplaybackCtlButton + onClicked: pauseBtnClicked() + } + + ImageText { + id: _forwardBtn + visible: true + anchors.bottom: _buttonRow.bottom + diameter: 85; //Variables.rinsebackIconDiameterDefault + source: "qrc:/images/iForward" + text: qsTr("Forward") + fontSize: 26; //Fonts.fontPixelplaybackCtlButton + onClicked: forwardBtnClicked() + } + } +} Index: sources/gui/qml/components/VideoScreen.qml =================================================================== diff -u -r85acfb989e40d697550f788b85a1d287b3316728 -r0f7ff0b328197a1737bd33cde56bac95fa98e1eb --- sources/gui/qml/components/VideoScreen.qml (.../VideoScreen.qml) (revision 85acfb989e40d697550f788b85a1d287b3316728) +++ sources/gui/qml/components/VideoScreen.qml (.../VideoScreen.qml) (revision 0f7ff0b328197a1737bd33cde56bac95fa98e1eb) @@ -1,4 +1,3 @@ - /*! * * Copyright (c) 2019-2025 Diality Inc. - All Rights Reserved. @@ -26,14 +25,14 @@ property alias source : _mediaplayer.source property bool showButtons : false - property int showButtonsTimeOut : 3000 // ms - property int transitionInterval : 300 // ms + property int showButtonsTimeOut : 3000 // ms // Variables.playbackCtrlBtnTimeOut; + property int transitionInterval : 300 // ms // Variables.playbackCtrlStepInterval property int stepsInterval : 5000 // ms visible : true backgroundRect.width : parent.width backgroundRect.height : parent.height - backgroundRect.color : "transparent" + backgroundRect.color : Colors.transparent; // Video Play Controller @@ -196,7 +195,7 @@ } ImageText { - id: _imageForeward + id: _imageForward visible: true enabled: !_mediaplayer.EndOfMedia || ((_mediaplayer.duration - _mediaplayer.position) > 0) ? true : false Index: sources/gui/qml/dialogs/DiagnosticsDialog.qml =================================================================== diff -u -r85acfb989e40d697550f788b85a1d287b3316728 -r0f7ff0b328197a1737bd33cde56bac95fa98e1eb --- sources/gui/qml/dialogs/DiagnosticsDialog.qml (.../DiagnosticsDialog.qml) (revision 85acfb989e40d697550f788b85a1d287b3316728) +++ sources/gui/qml/dialogs/DiagnosticsDialog.qml (.../DiagnosticsDialog.qml) (revision 0f7ff0b328197a1737bd33cde56bac95fa98e1eb) @@ -43,7 +43,13 @@ // Jira: LEAH-1976-implement-a-simple-video-screen // For testing the rest of code is comment out. // Please uncomment the rest of code later - VideoScreen { id: _video + // VideoScreen { id: _video + // anchors.centerIn: parent + // width : parent.width + // height : parent.height + // } + + AnimationScreen { id: _animationScreen anchors.centerIn: parent width : parent.width height : parent.height