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 }