Warning, /education/gcompris/src/activities/letter-in-word/LetterInWord.qml is written in an unsupported language. File is not indexed.

0001 /* GCompris - LetterInWord.qml
0002  *
0003  * SPDX-FileCopyrightText: 2014 Holger Kaelberer <holger.k@elberer.de>
0004  *               2016 Akshat Tandon <akshat.tandon@research.iiit.ac.in>
0005  *               2020 Timothée Giet <animtim@gmail.com>
0006 
0007  *
0008  * Authors:
0009  *   Holger Kaelberer <holger.k@elberer.de> (Click on Letter - Qt Quick port)
0010  *   Akshat Tandon <akshat.tandon@research.iiit.ac.in> (Adapt Click on Letter to make Letter in which word)
0011  *   Timothée Giet <animtim@gmail.com> (Refactoring, fixes and improvements)
0012  *
0013  *   SPDX-License-Identifier: GPL-3.0-or-later
0014  */
0015 
0016 import QtQuick 2.12
0017 import QtGraphicalEffects 1.0
0018 import GCompris 1.0
0019 import "../../core"
0020 import "letter-in-word.js" as Activity
0021 import "qrc:/gcompris/src/core/core.js" as Core
0022 
0023 ActivityBase {
0024     id: activity
0025     focus: true
0026 
0027     onStart: focus = true
0028 
0029     pageComponent: Image {
0030         id: background
0031         source: Activity.resUrl + "hillside.svg"
0032         sourceSize.width: parent.width
0033         sourceSize.height: parent.height
0034         fillMode: Image.PreserveAspectCrop
0035         focus: true
0036 
0037         // system locale by default
0038         property string locale: "system"
0039 
0040         property bool englishFallback: false
0041 
0042         signal start
0043         signal stop
0044         signal voiceError
0045 
0046         Component.onCompleted: {
0047             dialogActivityConfig.initialize()
0048             activity.start.connect(start)
0049             activity.stop.connect(stop)
0050         }
0051 
0052         QtObject {
0053             id: items
0054             property Item activityPage: activity
0055             property int currentLevel: activity.currentLevel
0056             property alias background: background
0057             property GCSfx audioEffects: activity.audioEffects
0058             property alias wordsModel: wordsModel
0059             property int currentLetterCase: ApplicationSettings.fontCapitalization
0060             property int currentMode: normalModeWordCount
0061             readonly property int easyModeWordCount: 5
0062             readonly property int normalModeWordCount: 11
0063             property GCAudio audioVoices: activity.audioVoices
0064             property alias parser: parser
0065             property alias animateX: animateX
0066             property alias repeatItem: repeatItem
0067             property alias score: score
0068             property alias bonus: bonus
0069             property alias errorRectangle: errorRectangle
0070             property alias locale: background.locale
0071             property alias questionItem: questionItem
0072             property alias englishFallbackDialog: englishFallbackDialog
0073             property string question
0074             property bool buttonsBlocked: false
0075         }
0076 
0077         onStart: {
0078             activity.audioVoices.error.connect(voiceError)
0079             Activity.start(items);
0080         }
0081 
0082         onStop: Activity.stop()
0083 
0084         onWidthChanged: {
0085                 animateX.restart();
0086         }
0087 
0088         onHeightChanged: {
0089                 animateX.restart();
0090         }
0091 
0092         DialogChooseLevel {
0093             id: dialogActivityConfig
0094             currentActivity: activity.activityInfo
0095             onClose: {
0096                 home();
0097             }
0098             onLoadData: {
0099                 if(activityData && activityData["locale"] && activityData["locale"] !== "system") {
0100                     background.locale = activityData["locale"];
0101                 }
0102                 else {
0103                     background.locale = Core.resolveLocale(background.locale)
0104                 }
0105                 if(activityData && activityData["savedLetterCase"]) {
0106                     items.currentLetterCase = activityData["savedLetterCase"];
0107                 }
0108                 if(activityData && activityData["savedMode"]) {
0109                     items.currentMode = activityData["savedMode"];
0110                 }
0111             }
0112             onStartActivity: {
0113                 background.stop();
0114                 background.start();
0115             }
0116         }
0117 
0118         DialogHelp {
0119             id: dialogHelpLeftRight
0120             onClose: home()
0121         }
0122 
0123         Bar {
0124             id: bar
0125             level: items.currentLevel + 1
0126             content: BarEnumContent { value: help | home | level | activityConfig }
0127             onHelpClicked: {
0128                 displayDialog(dialogHelpLeftRight)
0129             }
0130             onPreviousLevelClicked: Activity.previousLevel()
0131             onNextLevelClicked: Activity.nextLevel()
0132             onHomeClicked: home()
0133             onActivityConfigClicked: {
0134                 displayDialog(dialogActivityConfig);
0135             }
0136         }
0137 
0138         Score {
0139             id: score
0140             anchors {
0141                 right: parent.right
0142                 rightMargin: 10 * ApplicationInfo.ratio
0143                 bottom: wordsView.bottom
0144                 left: undefined
0145                 top: undefined
0146             }
0147             onStop: Activity.nextSubLevel();
0148         }
0149 
0150         Bonus {
0151             id: bonus
0152             interval: 100
0153             Component.onCompleted: {
0154                 win.connect(Activity.nextLevel);
0155             }
0156         }
0157 
0158         Item {
0159             id: planeText
0160             width: plane.width
0161             height: plane.height
0162             x: -width
0163             anchors.top: parent.top
0164             anchors.topMargin: 5 * ApplicationInfo.ratio
0165 
0166             Image {
0167                 id: plane
0168                 anchors.centerIn: planeText
0169                 anchors.top: parent.top
0170                 source: Activity.resUrl + "plane.svg"
0171                 sourceSize.height: repeatItem.width
0172             }
0173 
0174             GCText {
0175                 id: questionItem
0176 
0177                 anchors {
0178                     right: planeText.right
0179                     rightMargin: 2 * plane.width / 3
0180                     verticalCenter: planeText.verticalCenter
0181                     bottomMargin: 10 * ApplicationInfo.ratio
0182                 }
0183                 fontSize: hugeSize
0184                 font.weight: Font.DemiBold
0185                 color: "#2a2a2a"
0186                 text: items.question
0187             }
0188 
0189             PropertyAnimation {
0190                 id: animateX
0191                 target: planeText
0192                 properties: "x"
0193                 from: -planeText.width
0194                 //to:background.width/2 - planeText.width/2
0195                 to: bar.level <= 2 ? background.width/3.7 : background.width
0196                 duration: bar.level <= 2 ? 5500: 11000
0197                 //easing.type: Easing.OutQuad
0198                 easing.type: bar.level <= 2 ? Easing.OutQuad: Easing.OutInCirc
0199             }
0200         }
0201 
0202         BarButton {
0203             id: repeatItem
0204             source: "qrc:/gcompris/src/core/resource/bar_repeat.svg"
0205             sourceSize.width: 80 * ApplicationInfo.ratio
0206             anchors {
0207                 top: parent.top
0208                 right: parent.right
0209                 margins: 10
0210             }
0211             onClicked:{
0212                 if(!audioVoices.isPlaying() && !items.buttonsBlocked) {
0213                     Activity.playLetter(Activity.currentLetter);
0214                     animateX.restart();
0215                 }
0216             }
0217         }
0218 
0219         Keys.enabled: !items.buttonsBlocked
0220         Keys.onSpacePressed: wordsView.currentItem.select();
0221         Keys.onTabPressed: repeatItem.clicked();
0222         Keys.onEnterPressed: ok.clicked();
0223         Keys.onReturnPressed: ok.clicked();
0224         Keys.onRightPressed: wordsView.moveCurrentIndexRight();
0225         Keys.onLeftPressed: wordsView.moveCurrentIndexLeft();
0226         Keys.onDownPressed: wordsView.moveCurrentIndexDown();
0227         Keys.onUpPressed: wordsView.moveCurrentIndexUp();
0228 
0229         ListModel {
0230             id: wordsModel
0231         }
0232 
0233         property int itemWidth: Core.fitItems(wordsView.width, wordsView.height, wordsView.count);
0234 
0235         GridView {
0236             id: wordsView
0237             anchors.bottom: bar.top
0238             anchors.left: parent.left
0239             anchors.right: ok.left
0240             anchors.top: planeText.bottom
0241             anchors.topMargin: 0
0242             anchors.leftMargin: 10 * ApplicationInfo.ratio
0243             anchors.rightMargin: 10 * ApplicationInfo.ratio
0244             anchors.bottomMargin: bar.height * 0.5
0245             cellWidth: background.itemWidth
0246             cellHeight: background.itemWidth
0247             bottomMargin: 10 * ApplicationInfo.ratio
0248             clip: false
0249             interactive: false
0250             layoutDirection: Qt.LeftToRight
0251             currentIndex: -1
0252             highlight: gridHighlight
0253             highlightFollowsCurrentItem: true
0254             keyNavigationWraps: true
0255             model: wordsModel
0256             delegate: Card {
0257                 width: background.itemWidth
0258                 height: background.itemWidth - 10 * ApplicationInfo.ratio
0259                 mouseActive: !items.buttonsBlocked
0260             }
0261         }
0262 
0263         Component {
0264             id: gridHighlight
0265             Rectangle {
0266                 width: background.itemWidth
0267                 height: background.itemWidth
0268                 color:  "#AAFFFFFF"
0269                 Behavior on x { SpringAnimation { spring: 2; damping: 0.2 } }
0270                 Behavior on y { SpringAnimation { spring: 2; damping: 0.2 } }
0271             }
0272         }
0273 
0274         BarButton {
0275             id: ok
0276             source: "qrc:/gcompris/src/core/resource/bar_ok.svg"
0277             width: repeatItem.width
0278             height: width
0279             sourceSize.width: width
0280             anchors {
0281                 bottom: score.top
0282                 margins: 10 * ApplicationInfo.ratio
0283                 horizontalCenter: score.horizontalCenter
0284             }
0285             onClicked: {
0286                 if(!items.buttonsBlocked)
0287                     Activity.checkAnswer();
0288             }
0289         }
0290 
0291         ErrorRectangle {
0292             id: errorRectangle
0293             anchors.fill: wordsView
0294             radius: 10 * ApplicationInfo.ratio
0295             imageSize: Math.min(width, height) * 0.5
0296             function releaseControls() {
0297                 items.buttonsBlocked = false;
0298             }
0299         }
0300 
0301         JsonParser {
0302             id: parser
0303             onError: console.error("Letter-in-word: Error parsing JSON: " + msg);
0304         }
0305 
0306         Loader {
0307             id: englishFallbackDialog
0308             sourceComponent: GCDialog {
0309                 parent: activity
0310                 isDestructible: false
0311                 message: qsTr("We are sorry, we don't have yet a translation for your language.") + " " +
0312                          qsTr("GCompris is developed by the KDE community, you can translate GCompris by joining a translation team on <a href=\"%2\">%2</a>").arg("https://l10n.kde.org/") +
0313                          "<br /> <br />" +
0314                          qsTr("We switched to English for this activity but you can select another language in the configuration dialog.")
0315                 onClose: {
0316                     background.englishFallback = false;
0317                     Core.checkForVoices(activity);
0318                 }
0319             }
0320             anchors.fill: parent
0321             focus: true
0322             active: background.englishFallback
0323             onStatusChanged: if (status == Loader.Ready) item.start()
0324         }
0325     }
0326 }