Warning, /education/gcompris/src/activities/colors/FindIt.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - FindIt.qml
0002 *
0003 * SPDX-FileCopyrightText: 2015 Bruno Coudoin <bruno.coudoin@gcompris.net>
0004 *
0005 * Authors:
0006 * Pascal Georges <pascal.georges1@free.fr> (GTK+ version)
0007 * Bruno Coudoin <bruno.coudoin@gcompris.net> (Qt Quick port)
0008 * Timothée Giet <animtim@gmail.com> (refactoring and various improvements)
0009 *
0010 * SPDX-License-Identifier: GPL-3.0-or-later
0011 */
0012
0013 import QtQuick 2.12
0014 import QtGraphicalEffects 1.0
0015 import GCompris 1.0
0016
0017 import "../../core"
0018 import "findit.js" as Activity
0019 import "qrc:/gcompris/src/core/core.js" as Core
0020
0021 ActivityBase {
0022 id: activity
0023 focus: true
0024
0025 property var dataset
0026 property string backgroundImg
0027
0028 property string mode: ""
0029
0030 onStart: {
0031 focus = true;
0032 }
0033
0034 pageComponent: Image {
0035 id: background
0036 focus: true
0037 fillMode: Image.PreserveAspectCrop
0038 sourceSize.width: width
0039 sourceSize.height: height
0040 source: backgroundImg
0041
0042 property bool keyboardMode: false
0043 // if audio is disabled, we display a dialog to tell users this activity requires audio anyway
0044 property bool audioDisabled: false
0045
0046 signal start
0047 signal stop
0048
0049 Component.onCompleted: {
0050 activity.start.connect(start)
0051 activity.stop.connect(stop)
0052 }
0053 QtObject {
0054 id: items
0055 property Item activityPage: activity
0056 property alias background: background
0057 property int currentLevel: activity.currentLevel
0058 property alias bonus: bonus
0059 property alias containerModel: containerModel
0060 property alias initAnim: initAnim
0061 property alias nextAnim: nextAnim
0062 property alias fadeOutAnim: fadeOutAnim
0063 // On startup we want to queue the first sound but not after
0064 property bool firstQuestion: true
0065 property bool audioOk: false
0066 property alias score: score
0067 property bool objectSelected: true
0068 // we need to know the number of objects to calculate itemWidth before populating the container
0069 property int objectCount: 1
0070 // we need to copy tempModel to containerModel only once and only after all the rest is initialized
0071 property bool modelCopied: false
0072 }
0073 onStart: {
0074 if((!ApplicationSettings.isAudioVoicesEnabled || !ApplicationSettings.isAudioEffectsEnabled) && activity.isMusicalActivity) {
0075 background.audioDisabled = true;
0076 } else {
0077 Activity.start(items, dataset, mode);
0078 }
0079 }
0080 onStop: Activity.stop()
0081
0082 Keys.onPressed: {
0083 if(event.key === Qt.Key_Space) {
0084 container.currentItem.select()
0085 }
0086 }
0087 Keys.onReleased: {
0088 keyboardMode = true
0089 event.accepted = false
0090 }
0091 Keys.onEnterPressed: container.currentItem.select();
0092 Keys.onReturnPressed: container.currentItem.select();
0093 Keys.onRightPressed: container.moveCurrentIndexRight();
0094 Keys.onLeftPressed: container.moveCurrentIndexLeft();
0095 Keys.onDownPressed: container.moveCurrentIndexDown();
0096 Keys.onUpPressed: container.moveCurrentIndexUp();
0097 Keys.onTabPressed: if(repeatItem.visible) repeatItem.clicked();
0098
0099 ListModel {
0100 id: containerModel
0101 }
0102
0103 Rectangle {
0104 id: questionItem
0105 anchors.top: parent.top
0106 anchors.topMargin: 5 * ApplicationInfo.ratio
0107 anchors.horizontalCenter: parent.horizontalCenter
0108 width: questionText.contentWidth + 20 * ApplicationInfo.ratio
0109 height: Math.max(10 * ApplicationInfo.ratio, questionText.contentHeight + 5 * ApplicationInfo.ratio)
0110 radius: 5 * ApplicationInfo.ratio
0111 color: "#E2E2E2"
0112 border.color: "#373737"
0113 border.width: 2 * ApplicationInfo.ratio
0114 opacity: 0.01
0115
0116 function initQuestion() {
0117 questionText.text = Activity.getCurrentTextQuestion()
0118 if(Activity.getCurrentAudioQuestion()) {
0119 if(items.firstQuestion)
0120 items.audioOk = activity.audioVoices.append(Activity.getCurrentAudioQuestion())
0121 else {
0122 activity.audioVoices.clearQueue()
0123 items.audioOk = activity.audioVoices.play(Activity.getCurrentAudioQuestion())
0124 }
0125 items.firstQuestion = false
0126 }
0127 }
0128
0129 // initialization sequence for first question of first level
0130 SequentialAnimation {
0131 id: initAnim
0132 ScriptAction { script: questionItem.initQuestion() }
0133 PauseAnimation { duration: 50 }
0134 ScriptAction { script: if(!items.modelCopied)
0135 Activity.tempModelToContainer()
0136 }
0137 NumberAnimation { target: questionItem; property: "opacity"; to: 1; duration: 300 }
0138 }
0139
0140 // fade-out anim only before bonus start
0141 NumberAnimation { id: fadeOutAnim; target: questionItem; property: "opacity"; to: 0.01; duration: 300 }
0142
0143 // fade-out + init sequence after first question of a level
0144 SequentialAnimation {
0145 id: nextAnim
0146 NumberAnimation { target: questionItem; property: "opacity"; to: 0.01; duration: 300 }
0147 ScriptAction { script: initAnim.restart() }
0148 }
0149
0150 GCText {
0151 id: questionText
0152 anchors.centerIn: parent
0153 fontSize: largeSize
0154 width: background.width * 0.9
0155 horizontalAlignment: Text.AlignHCenter
0156 wrapMode: Text.WordWrap
0157 font.weight: Font.DemiBold
0158 color: "#373737"
0159 }
0160 }
0161
0162 GridView {
0163 id: container
0164 model: containerModel
0165 anchors.top: questionItem.bottom
0166 anchors.topMargin: 10 * ApplicationInfo.ratio
0167 anchors.bottom: score.top
0168 anchors.horizontalCenter: background.horizontalCenter
0169 width: background.width - score.width * 2
0170 interactive: false
0171 cellWidth: itemWidth
0172 cellHeight: itemWidth
0173 keyNavigationWraps: true
0174
0175 property int itemWidth: Core.fitItems(container.width, container.height, items.objectCount)
0176
0177 delegate: ColorItem {
0178 audioVoices: activity.audioVoices
0179 source: model.image
0180 audioSrc: model.audio ? model.audio : ""
0181 question: model.text
0182 sourceSize.height: container.itemWidth * 0.9
0183 sourceSize.width: container.itemWidth * 0.9
0184 }
0185 add: Transition {
0186 PathAnimation {
0187 path: Path {
0188 PathCurve { x: background.width / 3}
0189 PathCurve { y: background.height / 3}
0190 PathCurve {}
0191 }
0192 easing.type: Easing.InOutQuad
0193 duration: 2000
0194 }
0195 }
0196 highlight: Rectangle {
0197 width: container.cellWidth
0198 height: container.cellHeight
0199 color: "#AAFFFFFF"
0200 border.width: 3
0201 border.color: "black"
0202 visible: background.keyboardMode
0203 Behavior on x { SpringAnimation { spring: 2; damping: 0.2 } }
0204 Behavior on y { SpringAnimation { spring: 2; damping: 0.2 } }
0205 }
0206 }
0207
0208 DialogHelp {
0209 id: dialogHelp
0210 onClose: home()
0211 }
0212
0213 Bar {
0214 id: bar
0215 level: items.currentLevel + 1
0216 content: BarEnumContent { value: help | home | level }
0217 onHelpClicked: {
0218 displayDialog(dialogHelp)
0219 }
0220 onPreviousLevelClicked: Activity.previousLevel()
0221 onNextLevelClicked: Activity.nextLevel()
0222 onHomeClicked: activity.home()
0223 }
0224
0225 BarButton {
0226 id: repeatItem
0227 source: "qrc:/gcompris/src/core/resource/bar_repeat.svg";
0228 sourceSize.height: visible ? 80 * ApplicationInfo.ratio : 1
0229 z: bar.z + 1
0230 visible: items.audioOk
0231 anchors {
0232 bottom: bar.top
0233 right: parent.right
0234 margins: 10 * ApplicationInfo.ratio
0235 }
0236 onClicked: if (!activity.audioVoices.isPlaying())
0237 questionItem.initQuestion()
0238 }
0239
0240 Score {
0241 id: score
0242 anchors.bottom: bar.top
0243 anchors.right: bar.right
0244 anchors.left: parent.left
0245 anchors.bottomMargin: 10 * ApplicationInfo.ratio
0246 anchors.leftMargin: 10 * ApplicationInfo.ratio
0247 anchors.rightMargin: 0
0248 }
0249
0250 Bonus {
0251 id: bonus
0252 interval: 2000
0253 Component.onCompleted: win.connect(Activity.nextLevel)
0254 }
0255
0256 Loader {
0257 id: audioNeededDialog
0258 sourceComponent: GCDialog {
0259 parent: activity
0260 isDestructible: false
0261 message: qsTr("This activity requires sound, so it will play some sounds even if the audio voices or effects are disabled in the main configuration.")
0262 button1Text: qsTr("Quit")
0263 button2Text: qsTr("Continue")
0264 onButton1Hit: activity.home();
0265 onClose: {
0266 background.audioDisabled = false;
0267 Activity.start(items, dataset, mode);
0268 }
0269 }
0270 anchors.fill: parent
0271 focus: true
0272 active: background.audioDisabled
0273 onStatusChanged: if (status == Loader.Ready) item.start()
0274 }
0275 }
0276
0277 }