Warning, /education/gcompris/src/activities/hangman/Hangman.qml is written in an unsupported language. File is not indexed.

0001 /* GCompris - hangman.qml
0002  *
0003  * SPDX-FileCopyrightText: 2015 Rajdeep Kaur <rajdeep51994@gmail.com>
0004  *
0005  * Authors:
0006  *   Bruno Coudoin <bruno.coudoin@gcompris.net> (GTK+ version)
0007  *   Rajdeep kaur<rajdeep51994@gmail.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 import QtGraphicalEffects 1.0
0014 
0015 import "../../core"
0016 import "hangman.js" as Activity
0017 import "qrc:/gcompris/src/core/core.js" as Core
0018 
0019 ActivityBase {
0020     id: activity
0021 
0022     // Overload this in your activity to change it
0023     // Put you default-<locale>.json files in it
0024     property string dataSetUrl: "qrc:/gcompris/src/activities/hangman/resource/"
0025 
0026     onStart: focus = true
0027     onStop:  { }
0028     // When going on configuration, it steals the focus and re set it to the activity.
0029     // We need to set it back to the textinput item in order to have key events.
0030     onFocusChanged: {
0031         if(focus) {
0032             Activity.focusTextInput();
0033         }
0034     }
0035 
0036     pageComponent: Image {
0037         id: background
0038         source: activity.dataSetUrl + "background.svg"
0039         fillMode: Image.PreserveAspectCrop
0040         anchors.fill: parent
0041         sourceSize.width: width
0042         sourceSize.height: height
0043 
0044         // system locale by default
0045         property string locale: "system"
0046 
0047         property bool englishFallback: false
0048 
0049         signal start
0050         signal stop
0051 
0052         Component.onCompleted: {
0053             dialogActivityConfig.initialize()
0054             activity.start.connect(start)
0055             activity.stop.connect(stop)
0056         }
0057 
0058         // Add here the QML items you need to access in javascript
0059         QtObject {
0060             id: items
0061             property Item main: activity.main
0062             property alias background: background
0063             property Item ourActivity: activity
0064             property int currentLevel: activity.currentLevel
0065             property alias bonus: bonus
0066             property alias keyboard: keyboard
0067             property alias hidden: hidden
0068             property alias guessedText: guessedText
0069             property alias textinput: textinput
0070             property alias wordImage: wordImage
0071             property alias score: score
0072             property alias parser: parser
0073             property alias locale: background.locale
0074             property alias ok: ok
0075             property int remainingLife
0076             property double maskThreshold
0077             property var goodWord
0078             property int goodWordIndex
0079             property bool easyModeImage: true
0080             property bool easyModeAudio: true
0081             property alias englishFallbackDialog: englishFallbackDialog
0082             property alias winTimer: winTimer
0083             property alias goodIcon: goodIcon
0084 
0085             function playWord() {
0086                 var locale = ApplicationInfo.getVoicesLocale(items.locale)
0087                 if(activity.audioVoices.append(
0088                             ApplicationInfo.getAudioFilePathForLocale(goodWord.voice, locale)))
0089                     bonus.interval = 2500
0090                 else
0091                     bonus.interval = 500
0092             }
0093             onRemainingLifeChanged: {
0094                 maskThreshold = 0.15 * remainingLife
0095                 if(easyModeAudio && (remainingLife == 3)) {
0096                     playWord();
0097                 }
0098             }
0099         }
0100 
0101         onStart: {
0102             focus = true;
0103             Activity.start(items);
0104             if(!background.englishFallback)
0105                 Activity.focusTextInput();
0106         }
0107 
0108         onStop: {
0109             Activity.stop();
0110         }
0111 
0112         Image {
0113             id: goodIcon
0114             source: "qrc:/gcompris/src/core/resource/apply.svg"
0115             anchors.top: score.bottom
0116             anchors.horizontalCenter: score.horizontalCenter
0117             anchors.topMargin: ok.anchors.bottomMargin
0118             sourceSize.height: ok.width
0119             sourceSize.width: ok.width
0120             visible: false
0121         }
0122 
0123         GCText {
0124             id: hidden
0125             fontSize: largeSize
0126             color: "#4d4d4d"
0127             font.letterSpacing: 0.5
0128             width: parent.width * 0.90 - score.width
0129             fontSizeMode: Text.Fit
0130             horizontalAlignment: Text.AlignHCenter
0131             anchors {
0132                 right: score.left
0133                 bottom: bar.top
0134                 bottomMargin: 10 * ApplicationInfo.ratio
0135             }
0136             z: 11
0137         }
0138 
0139         GCText {
0140             id: guessedText
0141             fontSize: smallSize
0142             color: "#FFFFFF"
0143             wrapMode: Text.WordWrap
0144             width: guessedTextBg.width
0145             horizontalAlignment: Text.AlignHCenter
0146             anchors {
0147                 horizontalCenter: parent.horizontalCenter
0148             }
0149             z: 12
0150         }
0151 
0152         Rectangle {
0153             id: guessedTextBg
0154             width: parent.width * 0.7
0155             height: guessedText.height
0156             radius: 10
0157             border.color: "#121212"
0158             border.width: 1
0159             color: "#373737"
0160             anchors {
0161                 horizontalCenter: parent.horizontalCenter
0162             }
0163             z: 11
0164         }
0165 
0166         TextInput {
0167             // Helper element to capture composed key events like french รด which
0168             // are not available via Keys.onPressed() on linux. Must be
0169             // disabled on mobile!
0170             id: textinput
0171             enabled: !ApplicationInfo.isMobile
0172             visible: false
0173             focus: true
0174             onTextChanged: {
0175                 if (text != "") {
0176                     Activity.processKeyPress(text);
0177                     text = "";
0178                 }
0179             }
0180             onAccepted: if(items.remainingLife === 0) Activity.nextSubLevel()
0181         }
0182 
0183         Item {
0184                     id: imageframe
0185             width: Math.min(300 * ApplicationInfo.ratio,
0186                             background.width * 0.8,
0187                             hidden.y) - guessedText.height
0188             height: width
0189             anchors.horizontalCenter: parent.horizontalCenter
0190             anchors.top: guessedText.bottom
0191             y: 5 * ApplicationInfo.ratio
0192             z: 10
0193             opacity: items.easyModeImage ? 1 : 0
0194             Image {
0195                         id: wordImage
0196                         smooth: true
0197                 visible: false
0198 
0199                 anchors.fill: parent
0200                 property string nextSource
0201                 function changeSource(nextSource_) {
0202                     nextSource = nextSource_
0203                     animImage.start()
0204                 }
0205 
0206                 SequentialAnimation {
0207                     id: animImage
0208                     PropertyAnimation {
0209                         target: wordImage
0210                         property: "opacity"
0211                         to: 0
0212                         duration: 100
0213                     }
0214                     PropertyAction {
0215                         target: wordImage
0216                         property: "source"
0217                         value: wordImage.nextSource
0218                     }
0219                     PropertyAnimation {
0220                         target: wordImage
0221                         property: "opacity"
0222                         to: 1
0223                         duration: 100
0224                     }
0225                 }
0226             }
0227 
0228             Image {
0229                         id: threshmask
0230                 smooth: true
0231                 visible: false
0232                 width: 1.3*parent.width
0233                 height: 1.2*parent.height
0234                 source: dataSetUrl + "fog.png"
0235             }
0236 
0237             ThresholdMask {
0238                 id: thresh
0239                 anchors.fill: wordImage
0240                 source: wordImage
0241                 maskSource: threshmask
0242                 spread: 0.4
0243                 // remainingLife between 0 and 6 => threshold between 0 and 0.9
0244                 threshold: items.maskThreshold
0245             }
0246         }
0247 
0248         DialogChooseLevel {
0249             id: dialogActivityConfig
0250             currentActivity: activity.activityInfo
0251             onClose: {
0252                 home()
0253             }
0254             onSaveData: {
0255                 levelFolder = dialogActivityConfig.chosenLevels
0256                 currentActivity.currentLevels = dialogActivityConfig.chosenLevels
0257                 ApplicationSettings.setCurrentLevels(currentActivity.name, dialogActivityConfig.chosenLevels)
0258             }
0259             onLoadData: {
0260                 if(activityData && activityData["locale"]) {
0261                     background.locale = Core.resolveLocale(activityData["locale"]);
0262                 }
0263                 else {
0264                     background.locale = Core.resolveLocale(background.locale);
0265                 }
0266                 if(activityData) {
0267                     if(activityData["easyModeImage"])
0268                         items.easyModeImage = (activityData["easyModeImage"] === "true");
0269                     else if(activityData["easyMode"])
0270                         items.easyModeImage = (activityData["easyMode"] === "true");
0271                 }
0272                 if(activityData && activityData["easyModeAudio"]) {
0273                     items.easyModeAudio = (activityData["easyModeAudio"] === "true");
0274                 }
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             anchors.bottom: keyboard.top
0292             content: BarEnumContent { value: help | home | level | activityConfig }
0293             onHelpClicked: {
0294                 displayDialog(dialogHelp)
0295             }
0296             onPreviousLevelClicked: Activity.previousLevel()
0297             onNextLevelClicked: Activity.nextLevel()
0298             onHomeClicked: activity.home()
0299             onActivityConfigClicked: {
0300                 displayDialog(dialogActivityConfig)
0301             }
0302         }
0303 
0304         Score {
0305             id: score
0306             height: 1.2 * internalTextComponent.height
0307             width: 1.3 * internalTextComponent.width
0308             isScoreCounter: false
0309             anchors {
0310                 top: guessedTextBg.bottom
0311                 bottom: undefined
0312                 right: parent.right
0313                 margins: 0.025 * parent.width
0314             }
0315         }
0316 
0317         BarButton {
0318             id: ok
0319             source: "qrc:/gcompris/src/core/resource/bar_ok.svg";
0320             sourceSize.width: Math.min(score.width, clock.width)
0321             visible: false
0322             anchors {
0323                 top: score.bottom
0324                 horizontalCenter: score.horizontalCenter
0325                 topMargin: 5 * ApplicationInfo.ratio
0326             }
0327             onClicked: Activity.nextSubLevel()
0328         }
0329 
0330         JsonParser {
0331             id: parser
0332             onError: console.error("Hangman: Error parsing json: " + msg);
0333         }
0334 
0335         Image {
0336             id: clock
0337             anchors {
0338                 left: parent.left
0339                 top: guessedTextBg.bottom
0340                 margins: 0.025 * parent.width
0341             }
0342             sourceSize.width: 66 * bar.barZoom
0343             property int remainingLife: items.remainingLife
0344             onRemainingLifeChanged: if(remainingLife >= 0) clockAnim.restart()
0345 
0346             SequentialAnimation {
0347                 id: clockAnim
0348                 alwaysRunToEnd: true
0349                 ParallelAnimation {
0350                     NumberAnimation {
0351                         target: clock; properties: "opacity";
0352                         to: 0; duration: 800; easing.type: Easing.OutCubic
0353                     }
0354                     NumberAnimation {
0355                         target: clock; properties: "rotation"; from: 0; to: 180;
0356                         duration: 800; easing.type: Easing.OutCubic
0357                     }
0358                 }
0359                 PropertyAction {
0360                     target: clock; property: 'source';
0361                     value: "qrc:/gcompris/src/activities/reversecount/resource/" +
0362                            "flower" + items.remainingLife + ".svg"
0363                 }
0364                 ParallelAnimation {
0365                     NumberAnimation {
0366                         target: clock; properties: "opacity";
0367                         to: 1; duration: 800; easing.type: Easing.OutCubic
0368                     }
0369                     NumberAnimation {
0370                         target: clock; properties: "rotation"; from: 180; to: 0;
0371                         duration: 800; easing.type: Easing.OutCubic
0372                     }
0373                 }
0374             }
0375         }
0376 
0377         VirtualKeyboard {
0378             id: keyboard
0379             anchors.bottom: parent.bottom
0380             anchors.horizontalCenter: parent.horizontalCenter
0381             width: parent.width
0382             onKeypress: {
0383                 Activity.processKeyPress(text);
0384                 // Set the focus back to the InputText for keyboard input
0385                 Activity.focusTextInput();
0386             }
0387             onError: console.log("VirtualKeyboard error: " + msg);
0388         }
0389 
0390         Bonus {
0391             id: bonus
0392             interval: 2000
0393             onLoose: ok.visible = true
0394             onWin: Activity.nextSubLevel()
0395         }
0396 
0397         Loader {
0398             id: englishFallbackDialog
0399             sourceComponent: GCDialog {
0400                 parent: activity
0401                 isDestructible: false
0402                 message: qsTr("We are sorry, we don't have yet a translation for your language.") + " " +
0403                          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/") +
0404                          "<br /> <br />" +
0405                          qsTr("We switched to English for this activity but you can select another language in the configuration dialog.")
0406                 onClose: {
0407                     background.englishFallback = false;
0408                     Activity.focusTextInput;
0409                 }
0410             }
0411             anchors.fill: parent
0412             focus: true
0413             active: background.englishFallback
0414             onStatusChanged: if (status == Loader.Ready) item.start()
0415         }
0416 
0417         Timer {
0418             id: winTimer
0419             interval: 2000
0420             onTriggered: bonus.good("lion")
0421         }
0422     }
0423 }