Warning, /education/gcompris/src/activities/lang/ImageReview.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - lang.qml 0002 * 0003 * Copyright (C) Siddhesh suthar <siddhesh.it@gmail.com> (Qt Quick port) 0004 * 0005 * Authors: 0006 * Pascal Georges (pascal.georges1@free.fr) (GTK+ version) 0007 * Holger Kaelberer <holger.k@elberer.de> (Qt Quick port of imageid) 0008 * Siddhesh suthar <siddhesh.it@gmail.com> (Qt Quick port) 0009 * Bruno Coudoin <bruno.coudoin@gcompris.net> (Integration Lang dataset) 0010 * 0011 * SPDX-License-Identifier: GPL-3.0-or-later 0012 */ 0013 import QtQuick 2.12 0014 import GCompris 1.0 0015 import QtGraphicalEffects 1.0 0016 0017 import "../../core" 0018 import "lang.js" as Activity 0019 import "qrc:/gcompris/src/core/core.js" as Core 0020 0021 Item { 0022 id: imageReview 0023 anchors.fill: parent 0024 0025 property alias category: categoryText.text 0026 property int wordListIndex // This is the current sub list of words 0027 property var word: rootItem.opacity == 1 ? items.wordList[wordListIndex][score.currentSubLevel - 1] : undefined 0028 // miniGames is list of miniGames 0029 // first element is Activity name, 0030 // second element is mode of miniGame 0031 // third element is the qml to load 0032 property var miniGames: [ 0033 ["QuizActivity", 1, "Quiz.qml"], 0034 ["QuizActivity", 2, "Quiz.qml"], 0035 ["QuizActivity", 3, "Quiz.qml"], 0036 ["SpellActivity", 1, "SpellIt.qml"] 0037 ] 0038 property var currentMiniGame 0039 property var loadedItems 0040 property bool started: rootItem.opacity == 1 0041 0042 // Start at last wordListIndex 0043 function start() { 0044 initLevel(wordListIndex) 0045 } 0046 0047 // Start the image review at wordList sublesson 0048 function initLevel(wordListIndex_) { 0049 wordListIndex = wordListIndex_ 0050 score.currentSubLevel = 1 0051 score.numberOfSubLevels = items.wordList[wordListIndex].length 0052 focus = true 0053 forceActiveFocus() 0054 miniGameLoader.source = "" 0055 currentMiniGame = -1 0056 rootItem.opacity = 1 0057 } 0058 0059 function restoreMinigameFocus() { 0060 miniGameLoader.item.restoreFocus(); 0061 } 0062 0063 function stop() { 0064 focus = false 0065 rootItem.opacity = 0 0066 wordImage.changeSource('') 0067 wordText.changeText('') 0068 repeatItem.visible = false 0069 } 0070 0071 onWordChanged: { 0072 if(word) { 0073 if (Activity.playWord(word.voice)) { 0074 word['hasVoice'] = true 0075 repeatItem.visible = true 0076 } else { 0077 word['hasVoice'] = false 0078 repeatItem.visible = false 0079 } 0080 wordImage.changeSource(word.image) 0081 wordText.changeText(word.translatedTxt) 0082 } 0083 } 0084 0085 // Cheat codes to access mini games directly 0086 // Note: miniGame 2 (quiz on mode 3) can start only if at least the audio of 2 words 0087 // have been played on ImageReview step, else it skips to miniGame 3. So make sure 0088 // to view all the words on first step before loading miniGame 2. 0089 Keys.onPressed: { 0090 if((event.modifiers & Qt.ControlModifier) && (event.key === Qt.Key_1)) { 0091 initLevel(wordListIndex) 0092 event.accepted = true 0093 } 0094 if((event.modifiers & Qt.ControlModifier) && (event.key === Qt.Key_2)) { 0095 startMiniGame(0) 0096 event.accepted = true 0097 } 0098 if((event.modifiers & Qt.ControlModifier) && (event.key === Qt.Key_3)) { 0099 startMiniGame(1) 0100 event.accepted = true 0101 } 0102 if((event.modifiers & Qt.ControlModifier) && (event.key === Qt.Key_4)) { 0103 startMiniGame(2) 0104 event.accepted = true 0105 } 0106 if((event.modifiers & Qt.ControlModifier) && (event.key === Qt.Key_5)) { 0107 startMiniGame(3) 0108 event.accepted = true 0109 } 0110 } 0111 0112 Keys.onEscapePressed: { 0113 Activity.launchMenuScreen() 0114 } 0115 0116 Keys.onLeftPressed: { 0117 if( score.currentSubLevel > 1 ) { 0118 imageReview.prevWord() 0119 event.accepted = true 0120 } 0121 } 0122 Keys.onRightPressed: { 0123 imageReview.nextWord() 0124 event.accepted = true 0125 } 0126 Keys.onSpacePressed: { 0127 imageReview.nextWord() 0128 event.accepted = true 0129 } 0130 Keys.onEnterPressed: { 0131 imageReview.nextWord() 0132 event.accepted = true 0133 } 0134 Keys.onReturnPressed: { 0135 imageReview.nextWord() 0136 event.accepted = true 0137 } 0138 Keys.onTabPressed: { 0139 repeatItem.clicked() 0140 } 0141 0142 Keys.onReleased: { 0143 if (event.key === Qt.Key_Back) { 0144 event.accepted = true 0145 Activity.launchMenuScreen() 0146 } 0147 } 0148 0149 Item { 0150 id: rootItem 0151 anchors.fill: parent 0152 opacity: 0 0153 Behavior on opacity { PropertyAnimation { duration: 200 } } 0154 0155 Rectangle { 0156 id: categoryTextbg 0157 parent: rootItem 0158 width: Math.min(imageFrame.width + 8, imageBg.width * 1.5) 0159 height: 42 * ApplicationInfo.ratio 0160 color: "#AAFFFFFF" 0161 radius: 16 0162 anchors { 0163 horizontalCenter: parent.horizontalCenter 0164 top: rootItem.top 0165 topMargin: 4 * ApplicationInfo.ratio 0166 } 0167 0168 GCText { 0169 id: categoryText 0170 fontSizeMode: Text.Fit 0171 fontSize: mediumSize 0172 font.weight: Font.DemiBold 0173 width: parent.width - 8 0174 height: parent.height - 8 0175 horizontalAlignment: Text.AlignHCenter 0176 verticalAlignment: Text.AlignVCenter 0177 color: "#373737" 0178 anchors.centerIn: parent 0179 } 0180 } 0181 0182 Item { 0183 id: imageFrame 0184 parent: rootItem 0185 width: (parent.width - previousWordButton.width * 2) * 0.8 0186 height: (parent.height - categoryTextbg.height - wordTextbg.height - bar.height * 1.1) * 0.8 0187 anchors { 0188 horizontalCenter: parent.horizontalCenter 0189 top: categoryTextbg.bottom 0190 margins: 10 * ApplicationInfo.ratio 0191 } 0192 z: 11 0193 0194 Rectangle { 0195 id: imageBg 0196 color: "#E0E0F7" 0197 anchors.centerIn: parent 0198 width: Math.min(parent.width, parent.height) 0199 height: width 0200 radius: width * 0.1 0201 border.color: "#373737" 0202 border.width: ApplicationInfo.ratio 0203 } 0204 0205 Image { 0206 id: wordImage 0207 // Images are not svg 0208 width: imageBg.height * 0.9 0209 height: width 0210 anchors.centerIn: parent 0211 0212 property string nextSource 0213 function changeSource(nextSource_) { 0214 nextSource = nextSource_ 0215 animImage.restart() 0216 } 0217 0218 SequentialAnimation { 0219 id: animImage 0220 PropertyAnimation { 0221 target: wordImage 0222 property: "opacity" 0223 to: 0 0224 duration: 100 0225 } 0226 PropertyAction { 0227 target: wordImage 0228 property: "source" 0229 value: wordImage.nextSource 0230 } 0231 PropertyAnimation { 0232 target: wordImage 0233 property: "opacity" 0234 to: 1 0235 duration: 100 0236 } 0237 } 0238 MouseArea { 0239 anchors.fill: parent 0240 enabled: rootItem.opacity == 1 0241 onClicked: Activity.playWord(word.voice) 0242 } 0243 } 0244 } 0245 0246 Item { 0247 id: previousButtonArea 0248 anchors.left: rootItem.left 0249 anchors.top: imageFrame.top 0250 anchors.bottom: imageFrame.bottom 0251 width: (rootItem.width - imageBg.width) * 0.5 0252 0253 Image { 0254 id: previousWordButton 0255 source: "qrc:/gcompris/src/core/resource/bar_previous.svg"; 0256 width: 36 * ApplicationInfo.ratio 0257 sourceSize.width: width 0258 visible: score.currentSubLevel > 1 ? true : false 0259 anchors.centerIn: parent 0260 0261 MouseArea { 0262 anchors.centerIn: parent 0263 enabled: rootItem.opacity == 1 0264 width: parent.width * 3 0265 height: parent.height * 2 0266 onClicked: imageReview.prevWord() 0267 } 0268 } 0269 } 0270 0271 Item { 0272 id: nextButtonArea 0273 anchors.right: rootItem.right 0274 anchors.top: imageFrame.top 0275 anchors.bottom: imageFrame.bottom 0276 width: previousButtonArea.width 0277 0278 Image { 0279 id: nextWordButton 0280 source: "qrc:/gcompris/src/core/resource/bar_next.svg"; 0281 width: previousWordButton.width 0282 sourceSize.width: width 0283 anchors.centerIn: parent 0284 0285 MouseArea { 0286 anchors.centerIn: parent 0287 enabled: rootItem.opacity == 1 0288 width: parent.width * 3 0289 height: parent.height * 2 0290 onClicked: imageReview.nextWord(); 0291 } 0292 } 0293 } 0294 0295 Rectangle { 0296 id: wordTextbg 0297 parent: rootItem 0298 width: Math.min(imageFrame.width + 8, imageBg.width * 2) 0299 height: 64 * ApplicationInfo.ratio 0300 color: "#AAFFFFFF" 0301 radius: 16 0302 anchors { 0303 horizontalCenter: parent.horizontalCenter 0304 top: imageFrame.bottom 0305 margins: 10 * ApplicationInfo.ratio 0306 } 0307 0308 GCText { 0309 id: wordText 0310 text: "" 0311 fontSizeMode: Text.Fit 0312 fontSize: largeSize 0313 font.weight: Font.DemiBold 0314 width: parent.width - 8 0315 height: parent.height - 8 0316 horizontalAlignment: Text.AlignHCenter 0317 verticalAlignment: Text.AlignVCenter 0318 anchors.centerIn: parent 0319 color: "#373737" 0320 0321 property string nextWord 0322 function changeText(nextWord_) { 0323 nextWord = nextWord_ 0324 animWord.restart() 0325 } 0326 0327 SequentialAnimation { 0328 id: animWord 0329 PropertyAnimation { 0330 target: wordText 0331 property: "opacity" 0332 to: 0 0333 duration: 100 0334 } 0335 PropertyAction { 0336 target: wordText 0337 property: "text" 0338 value: wordText.nextWord 0339 } 0340 PropertyAnimation { 0341 target: wordText 0342 property: "opacity" 0343 to: 1 0344 duration: 100 0345 } 0346 } 0347 } 0348 } 0349 0350 BarButton { 0351 id: repeatItem 0352 parent: rootItem 0353 source: "qrc:/gcompris/src/core/resource/bar_repeat.svg"; 0354 sourceSize.width: Math.min(categoryTextbg.x, 84 * ApplicationInfo.ratio) - 2 * anchors.margins 0355 0356 z: 12 0357 anchors { 0358 top: parent.top 0359 left: parent.left 0360 margins: 10 * ApplicationInfo.ratio 0361 } 0362 onClicked: Activity.playWord(imageReview.word.voice) 0363 Behavior on opacity { PropertyAnimation { duration: 200 } } 0364 } 0365 0366 Score { 0367 id: score 0368 parent: rootItem 0369 isScoreCounter: false 0370 } 0371 } 0372 Loader { 0373 id: miniGameLoader 0374 width: parent.width 0375 height: parent.height 0376 anchors.fill: parent 0377 asynchronous: false 0378 } 0379 0380 function nextPressed() { 0381 if(currentMiniGame === 0) { 0382 nextSubLevel() 0383 } 0384 } 0385 0386 function nextWord() { 0387 ++score.currentSubLevel; 0388 0389 if(score.currentSubLevel == score.numberOfSubLevels + 1) { 0390 nextMiniGame() 0391 } 0392 } 0393 0394 function prevWord() { 0395 --score.currentSubLevel 0396 } 0397 0398 function startMiniGame(miniGameIndex) { 0399 currentMiniGame = miniGameIndex 0400 var mode = miniGames[miniGameIndex][1]; 0401 var itemToLoad = miniGames[miniGameIndex][2]; 0402 0403 // Starting a minigame we don't want pending voices to play 0404 Activity.clearVoiceQueue() 0405 0406 // preparing the wordList 0407 var wordList = Core.shuffle(items.wordList[wordListIndex]).slice() 0408 0409 miniGameLoader.source = itemToLoad; 0410 var loadedItems = miniGameLoader.item 0411 0412 rootItem.opacity = 0 0413 focus = false 0414 0415 // Initiate the loaded item mini game 0416 // Some Mini Games may not start because they miss voices 0417 // In this case we try the next one 0418 if(!loadedItems.init(loadedItems, wordList, mode)) 0419 nextMiniGame() 0420 } 0421 0422 //called by a miniGame when it is won 0423 function nextMiniGame() { 0424 if(currentMiniGame < miniGames.length - 1) { 0425 startMiniGame(++currentMiniGame) 0426 } else { 0427 Activity.markProgress() 0428 if(wordListIndex < items.wordList.length - 1) { 0429 initLevel(wordListIndex + 1) 0430 } else { 0431 Activity.launchMenuScreen() 0432 miniGameLoader.source = "" 0433 } 0434 } 0435 } 0436 }