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

0001 /* GCompris - missing-letter.qml
0002  *
0003  * Copyright (C) 2014 "Amit Tomar" <a.tomar@outlook.com>
0004  *
0005  * Authors:
0006  *   "Pascal Georges" <pascal.georgis1.free.fr> (GTK+ version)
0007  *   "Amit Tomar" <a.tomar@outlook.com> (Qt Quick port)
0008  *
0009  *   SPDX-License-Identifier: GPL-3.0-or-later
0010  */
0011 import QtQuick 2.12
0012 import GCompris 1.0
0013 
0014 import "../../core"
0015 import "qrc:/gcompris/src/core/core.js" as Core
0016 import "missing-letter.js" as Activity
0017 
0018 ActivityBase {
0019     id: activity
0020 
0021     onStart: focus = true
0022     onStop: {}
0023 
0024     // When going on configuration, it steals the focus and re set it to the activity.
0025     // We need to set it back to the textinput item in order to have key events.
0026     onFocusChanged: {
0027         if(focus) {
0028             Activity.focusTextInput()
0029         }
0030     }
0031     pageComponent: Image {
0032         id: background
0033         source: Activity.url + "background.svg"
0034         sourceSize.width: width
0035         sourceSize.height: height
0036         fillMode: Image.PreserveAspectCrop
0037 
0038         // system locale by default
0039         property string locale: "system"
0040 
0041         property bool englishFallback: false
0042         property bool downloadWordsNeeded: false
0043 
0044         signal start
0045         signal stop
0046 
0047         Component.onCompleted: {
0048             dialogActivityConfig.initialize()
0049             activity.start.connect(start)
0050             activity.stop.connect(stop)
0051         }
0052 
0053         // Add here the QML items you need to access in javascript
0054         QtObject {
0055             id: items
0056             property Item main: activity.main
0057             property alias background: background
0058             property int currentLevel: activity.currentLevel
0059             property alias bonus: bonus
0060             property alias score: score
0061             property alias questionImage: questionImage
0062             property alias questionText: questionText
0063             property alias questionAnim: questionAnim
0064             property alias answers: answers
0065             property GCAudio audioVoices: activity.audioVoices
0066             property alias englishFallbackDialog: englishFallbackDialog
0067             property alias parser: parser
0068             property alias locale: background.locale
0069             property string answer
0070             property alias textinput: textinput
0071             property bool isGoodAnswer: false
0072             property bool buttonsBlocked: false
0073         }
0074 
0075         onStart: {
0076             Activity.init(items)
0077             Activity.focusTextInput()
0078             Activity.start()
0079         }
0080         onStop: {
0081             Activity.stop()
0082         }
0083 
0084         function goodAnswer() {
0085             items.buttonsBlocked = true;
0086             score.currentSubLevel++;
0087             score.playWinAnimation();
0088             questionAnim.start();
0089             Activity.showAnswer();
0090         }
0091 
0092         TextInput {
0093             // Helper element to capture composed key events like french รด which
0094             // are not available via Keys.onPressed() on linux. Must be
0095             // disabled on mobile!
0096             id: textinput
0097             anchors.centerIn: background
0098             enabled: !ApplicationInfo.isMobile
0099             focus: true
0100             visible: false
0101 
0102             onTextChanged: {
0103                 if (text != '') {
0104                     var typedText = text
0105                     var answerText = Activity.getCurrentQuestion().answer
0106                     if(ApplicationSettings.fontCapitalization === Font.AllUppercase)
0107                         typedText = text.toLocaleUpperCase()
0108                     else if(ApplicationSettings.fontCapitalization === Font.AllLowercase)
0109                         typedText = text.toLocaleLowerCase()
0110 
0111                     if(!items.isGoodAnswer && (typedText === answerText)) {
0112                         background.goodAnswer();
0113                     }
0114                     text = '';
0115                 }
0116             }
0117 
0118             Keys.onTabPressed: bar.repeatClicked();
0119         }
0120 
0121         Item {
0122             id: layoutArea
0123             anchors.top: score.bottom
0124             anchors.bottom: bar.top
0125             anchors.bottomMargin: bar.height * 0.4
0126             anchors.left: background.left
0127             anchors.right: background.right
0128             anchors.margins: 10 * ApplicationInfo.ratio
0129         }
0130 
0131         Item {
0132             id: questionArea
0133             width: Math.min(layoutArea.width, layoutArea.height)
0134             height: width
0135             anchors.centerIn: layoutArea
0136         }
0137 
0138         // Buttons with possible answers shown on the left of screen
0139         Column {
0140             id: buttonHolder
0141             spacing: 10 * ApplicationInfo.ratio
0142             anchors.left: questionArea.left
0143             anchors.top: questionArea.top
0144 
0145             add: Transition {
0146                 NumberAnimation { properties: "y"; from: holder.y; duration: 500 }
0147             }
0148 
0149             Repeater {
0150                 id: answers
0151 
0152                 AnswerButton {
0153                     width: questionArea.width - holder.width - 10 * ApplicationInfo.ratio
0154                     height: (holder.height
0155                              - buttonHolder.spacing * answers.model.length) / answers.model.length
0156                     textLabel: modelData
0157                     blockAllButtonClicks: items.buttonsBlocked
0158                     isCorrectAnswer: modelData === items.answer
0159                     onPressed: {
0160                         items.buttonsBlocked = true
0161                         if(!items.isGoodAnswer) {
0162                             modelData == items.answer ? background.goodAnswer() : ''
0163                         }
0164                     }
0165                     onIncorrectlyPressed: items.buttonsBlocked = false
0166                 }
0167             }
0168         }
0169 
0170         // Picture holder for different images being shown
0171         Rectangle {
0172             id: holder
0173             width: questionArea.width * 0.7
0174             height: questionArea.height
0175             anchors.top: questionArea.top
0176             anchors.right: questionArea.right
0177             color: "white"
0178             radius: 10
0179             border.width: 2
0180             border.color: "#373737"
0181             gradient: Gradient {
0182                 GradientStop { position: 0.0; color: "#80FFFFFF" }
0183                 GradientStop { position: 0.9; color: "#80EEEEEE" }
0184                 GradientStop { position: 1.0; color: "#80AAAAAA" }
0185             }
0186 
0187             Image {
0188                 id: questionImage
0189                 anchors.horizontalCenter: holder.horizontalCenter
0190                 anchors.top: holder.top
0191                 width: holder.width
0192                 height: width
0193                 fillMode: Image.PreserveAspectFit
0194             }
0195 
0196             Rectangle {
0197                 id: questionTextBg
0198                 width: holder.width
0199                 height: holder.height - questionImage.height
0200                 anchors.horizontalCenter: holder.horizontalCenter
0201                 anchors.top: questionImage.bottom
0202                 radius: 10
0203                 color: "#373737"
0204 
0205                 GCText {
0206                     id: questionText
0207                     horizontalAlignment: Text.AlignHCenter
0208                     verticalAlignment: Text.AlignVCenter
0209                     color: "#f2f2f2"
0210                     anchors.centerIn: parent
0211                     width: parent.width * 0.9
0212                     height: parent.height * 0.9
0213                     font.pointSize: NaN  // need to clear font.pointSize explicitly
0214                     fontSizeMode: Text.Fit
0215                     minimumPixelSize: 10
0216                     font.pixelSize: width * 0.2
0217 
0218                     SequentialAnimation {
0219                         id: questionAnim
0220                         NumberAnimation {
0221                             target: questionText
0222                             property: 'scale'
0223                             to: 1.05
0224                             duration: 500
0225                             easing.type: Easing.OutQuad
0226                         }
0227                         NumberAnimation {
0228                             target: questionText
0229                             property: 'scale'
0230                             to: 0.95
0231                             duration: 1000
0232                             easing.type: Easing.OutQuad
0233                         }
0234                         NumberAnimation {
0235                             target: questionText
0236                             property: 'scale'
0237                             to: 1.0
0238                             duration: 500
0239                             easing.type: Easing.OutQuad
0240                         }
0241                         ScriptAction {
0242                             script: Activity.nextSubLevel()
0243                         }
0244                     }
0245                 }
0246             }
0247         }
0248 
0249         Score {
0250             id: score
0251             anchors.bottom: undefined
0252             anchors.bottomMargin: 10 * ApplicationInfo.ratio
0253             anchors.right: parent.right
0254             anchors.rightMargin: 10 * ApplicationInfo.ratio
0255             anchors.top: parent.top
0256         }
0257 
0258         DialogChooseLevel {
0259             id: dialogActivityConfig
0260             currentActivity: activity.activityInfo
0261             onClose: {
0262                 home()
0263             }
0264             onSaveData: {
0265                 levelFolder = dialogActivityConfig.chosenLevels
0266                 currentActivity.currentLevels = dialogActivityConfig.chosenLevels
0267                 ApplicationSettings.setCurrentLevels(currentActivity.name, dialogActivityConfig.chosenLevels)
0268             }
0269             onLoadData: {
0270                 if(activityData && activityData["locale"]) {
0271                     background.locale = Core.resolveLocale(activityData["locale"]);
0272                 }
0273                 else {
0274                     background.locale = Core.resolveLocale(background.locale);
0275                 }
0276             }
0277             onStartActivity: {
0278                 background.stop()
0279                 background.start()
0280             }
0281         }
0282 
0283         DialogHelp {
0284             id: dialogHelp
0285             onClose: home()
0286         }
0287 
0288         Bar {
0289             id: bar
0290             level: items.currentLevel + 1
0291             content: BarEnumContent { value: help | home | level | repeat | activityConfig }
0292             onHelpClicked: displayDialog(dialogHelp)
0293             onPreviousLevelClicked: Activity.previousLevel()
0294             onNextLevelClicked: Activity.nextLevel()
0295             onHomeClicked: activity.home()
0296             onRepeatClicked: {
0297                 if(!audioVoices.isPlaying() && !items.buttonsBlocked) {
0298                     Activity.playCurrentWord()
0299                 }
0300             }
0301             onActivityConfigClicked: {
0302                 displayDialog(dialogActivityConfig)
0303             }
0304         }
0305 
0306         Bonus {
0307             id: bonus
0308             onStart: items.buttonsBlocked = true
0309             onStop: items.buttonsBlocked = false
0310             Component.onCompleted: win.connect(Activity.nextLevel)
0311         }
0312 
0313         JsonParser {
0314             id: parser
0315             onError: console.error("missing letter: Error parsing json: " + msg);
0316         }
0317 
0318         Loader {
0319             id: englishFallbackDialog
0320             sourceComponent: GCDialog {
0321                 parent: activity
0322                 isDestructible: false
0323                 message: qsTr("We are sorry, we don't have yet a translation for your language.") + " " +
0324                          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/") +
0325                          "<br /> <br />" +
0326                          qsTr("We switched to English for this activity but you can select another language in the configuration dialog.")
0327                 onClose: background.englishFallback = false
0328             }
0329             anchors.fill: parent
0330             focus: true
0331             active: background.englishFallback
0332             onStatusChanged: if (status == Loader.Ready) item.start()
0333         }
0334 
0335     }
0336 }