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

0001 /* GCompris - ExploreLevels.qml
0002 *
0003 * SPDX-FileCopyrightText: 2015 Ayush Agrawal <ayushagrawal288@gmail.com>
0004 *
0005 * Authors:
0006 *   Beth Hadley <bethmhadley@gmail.com> (GTK+ version)
0007 *   Ayush Agrawal <ayushagrawal288@gmail.com> (Qt Quick port)
0008 *   Djalil MESLI <djalilmesli@gmail.com> (Qt Quick port)
0009 *   Johnny Jazeix <jazeix@gmail.com> (Qt Quick port)
0010 *
0011 *   SPDX-License-Identifier: GPL-3.0-or-later
0012 */
0013 
0014 import QtQuick 2.12
0015 import GCompris 1.0
0016 import QtQuick.Controls 2.12
0017 
0018 import "../../core"
0019 import "explore-level.js" as Activity
0020 
0021 ActivityBase {
0022     id: activity
0023 
0024     property int numberOfLevels
0025     property string url
0026     property bool hasAudioQuestions
0027     property bool needsVoices: false
0028 
0029     onStart: focus = true
0030     onStop: {}
0031 
0032     isMusicalActivity: needsVoices
0033 
0034     pageComponent: Image {
0035         id: background
0036         source: "qrc:/gcompris/src/activities/chess/resource/background-wood.svg"
0037         width: parent.width
0038         height: parent.height
0039         sourceSize.width: width
0040         sourceSize.height: height
0041 
0042         // if audio is disabled, we display a dialog to tell users this activity requires audio anyway
0043         property bool audioDisabled: false
0044 
0045         /* In order to accept any screen ratio the play area is always a 1000x1000
0046          * square and is centered in a big background image that is 3000x3000
0047          */
0048 
0049         Image {
0050             id: bg
0051             source: dataset.item.backgroundImage
0052             sourceSize.width: width
0053             sourceSize.height: width
0054             width: 3000 * background.playRatio
0055             height: width
0056             anchors.centerIn: parent
0057         }
0058 
0059         property int playX: (activity.width - playWidth) / 2
0060         property int playY: (activity.height - playHeight) / 2
0061         property int playWidth: Math.min(activity.height - (bar.height * 2.2), activity.width)
0062         property int playHeight: playWidth
0063         property double playRatio: playWidth / 1000
0064 
0065         focus: true
0066 
0067         signal start
0068         signal stop
0069         signal voiceDone
0070 
0071         Component.onCompleted: {
0072             activity.start.connect(start)
0073             activity.stop.connect(stop)
0074         }
0075 
0076         // Add here the QML items you need to access in javascript
0077         QtObject {
0078             id: items
0079 
0080             property GCAudio audioVoices: activity.audioVoices
0081             property GCSfx audioEffects: activity.audioEffects
0082             property Item main: activity.main
0083             property int currentLevel: activity.currentLevel
0084             property alias bonus: bonus
0085             property alias score: score
0086             property alias progressbar: progressbar
0087             property alias errorRectangle: errorRectangle
0088             property alias dataModel: dataModel
0089             property alias dataset: dataset
0090             property alias instruction: instruction
0091             property alias descriptionPanel: descriptionPanel
0092             property bool hasAudioQuestions: activity.hasAudioQuestions
0093             property var questionOrder
0094             property var currentQuestion: ""
0095             property alias okButton: okButton
0096             property bool bonusPlaying: false
0097             property bool buttonsBlocked: false
0098             property bool descriptionBonusDone: false
0099         }
0100 
0101         Loader {
0102             id: dataset
0103             asynchronous: false
0104             onStatusChanged: {
0105                 if (status == Loader.Ready) {
0106                     // create table of size N filled with numbers from 0 to N
0107                     items.questionOrder = Array.apply(null, {length: items.dataModel.count}).map(Number.call, Number)
0108                 }
0109             }
0110         }
0111 
0112         onStart: {
0113             activity.audioVoices.done.connect(voiceDone)
0114             activity.audioEffects.done.connect(voiceDone)
0115             Activity.start(items, url, numberOfLevels)
0116             if(activity.needsVoices === true) {
0117                 if(!ApplicationSettings.isAudioVoicesEnabled || !ApplicationSettings.isAudioEffectsEnabled)
0118                     background.audioDisabled = true
0119             }
0120         }
0121         onStop: { Activity.stop() }
0122 
0123         Keys.onEscapePressed: {
0124             descriptionPanel.visible ? descriptionPanel.closeDescriptionPanel() : home()
0125         }
0126 
0127         onVoiceDone: {
0128             if(items.bonusPlaying) {
0129                 items.bonusPlaying = false;
0130                 Activity.repeat();
0131             }
0132         }
0133 
0134         Repeater {
0135             id: dataModel
0136             model: dataset && dataset.item && dataset.item.tab ? dataset.item.tab.length : 0
0137             AnimalLevels {
0138                 questionId: index
0139                 source: dataset.item.tab[index].image
0140                 x: Math.round(background.playX + background.playWidth * dataset.item.tab[index].x - width / 2)
0141                 y: Math.round(background.playY + background.playHeight * dataset.item.tab[index].y - height / 2)
0142                 width: Math.round(background.playWidth * dataset.item.tab[index].width)
0143                 height: Math.round(background.playHeight * dataset.item.tab[index].height)
0144                 title: dataset.item.tab[index].title
0145                 description: dataset.item.tab[index].text
0146                 imageSource: dataset.item.tab[index].image2
0147                 question: dataset.item.tab[index].text2
0148                 audio: dataset.item.tab[index].audio !== undefined ? dataset.item.tab[index].audio : ""
0149                 Component.onCompleted: {
0150                     displayDescription.connect(displayDescriptionItem)
0151                 }
0152             }
0153         }
0154 
0155         function displayDescriptionItem(animal) {
0156             descriptionPanel.title = animal.title
0157             descriptionPanel.description = animal.description
0158             descriptionPanel.imageSource = animal.imageSource
0159             descriptionPanel.visible = true
0160             descriptionPanel.showDescriptionPanel()
0161         }
0162 
0163         AnimalDescriptionLevels {
0164             id: descriptionPanel
0165             width: background.width
0166             height: background.height - bar.height * 1.2
0167             z: instruction.z + 1
0168         }
0169 
0170         Column {
0171             id: progress
0172             visible: items.score.currentSubLevel != 1
0173             anchors.bottom: bar.top
0174             anchors.right: parent.right
0175             anchors.rightMargin: 10 * ApplicationInfo.ratio
0176             anchors.bottomMargin: progressbar.height
0177             Score {
0178                 id: progressbar
0179                 anchors {
0180                     top: undefined
0181                     bottom: undefined
0182                     left: undefined
0183                     right: undefined
0184                 }
0185                 onStop: Activity.nextSubSubLevel();
0186             }
0187         }
0188 
0189         Image {
0190             id: okButton
0191             visible: false
0192             source:"qrc:/gcompris/src/core/resource/bar_ok.svg"
0193             sourceSize.width: questionText.height * 2
0194             fillMode: Image.PreserveAspectFit
0195             anchors.right: progress.right
0196             anchors.verticalCenter: progress.verticalCenter
0197             anchors.margins: 10 * ApplicationInfo.ratio
0198             MouseArea {
0199                 anchors.fill: parent
0200                 onClicked: Activity.nextLevel()
0201             }
0202         }
0203 
0204         Row {
0205             id: row
0206             spacing: 10 * ApplicationInfo.ratio
0207             anchors.fill: parent
0208             anchors.margins: 10 * ApplicationInfo.ratio
0209             layoutDirection: leftCol.width === 0 ? Qt.RightToLeft : Qt.LeftToRight
0210             Column {
0211                 id: leftCol
0212                 spacing: 10 * ApplicationInfo.ratio
0213 
0214                 Rectangle {
0215                     id: instruction
0216                     width: row.width - rightCol.width - 10 * ApplicationInfo.ratio
0217                     height: instructionText.height
0218                     color: "#CCCCCCCC"
0219                     radius: 10
0220                     border.width: 3
0221                     border.color: "black"
0222 
0223                     GCText {
0224                         id: instructionText
0225                         horizontalAlignment: Text.AlignHCenter
0226                         verticalAlignment: Text.AlignVCenter
0227                         anchors.centerIn: parent.Center
0228                         color: "black"
0229                         width: parent.width
0230                         wrapMode: Text.Wrap
0231                         text: (dataset.item && items.score.currentSubLevel - 1 != items.score.numberOfSubLevels  && items.score.currentSubLevel != 0) ? dataset.item.instructions[items.score.currentSubLevel - 1].text : ""
0232                     }
0233                     MouseArea {
0234                         anchors.fill: parent
0235                         onClicked: instruction.visible = false
0236                         enabled: instruction.visible
0237                     }
0238                 }
0239 
0240                 Rectangle {
0241                     id: question
0242                     width: row.width - rightCol.width - 10 * ApplicationInfo.ratio
0243                     height: questionText.height
0244                     color: '#CCCCCCCC'
0245                     radius: 10
0246                     border.width: 3
0247                     border.color: "black"
0248                     visible: items.score.currentSubLevel == 3 || (items.score.currentSubLevel == 2 && !items.hasAudioQuestions)
0249                     GCText {
0250                         id: questionText
0251                         horizontalAlignment: Text.AlignHCenter
0252                         verticalAlignment: Text.AlignVCenter
0253                         anchors.centerIn: parent.Center
0254                         color: "black"
0255                         width: parent.width
0256                         wrapMode: Text.Wrap
0257                         text: items.currentQuestion ? items.currentQuestion.text2 : ""
0258                     }
0259                 }
0260             }
0261 
0262             Column {
0263                 id: rightCol
0264                 spacing: 10 * ApplicationInfo.ratio
0265 
0266                 Score {
0267                     id: score
0268                     isScoreCounter: false
0269                     anchors {
0270                         bottom: undefined
0271                         right: undefined
0272                     }
0273                 }
0274 
0275                 BarButton {
0276                     id: repeatItem
0277                     source: "qrc:/gcompris/src/core/resource/bar_repeat.svg";
0278                     sourceSize.width: 60 * ApplicationInfo.ratio
0279                     anchors.right: parent.right
0280                     visible: items.score.currentSubLevel == 2 && activity.hasAudioQuestions //&& ApplicationSettings.isAudioVoicesEnabled
0281                     onClicked: {
0282                         if(!items.audioVoices.isPlaying()) {
0283                             Activity.repeat();
0284                         }
0285                     }
0286                 }
0287             }
0288         }
0289 
0290         ErrorRectangle {
0291             id: errorRectangle
0292             anchors.centerIn: parent
0293             width: 0
0294             height: 0
0295             imageSize: 60 * ApplicationInfo.ratio
0296             function releaseControls() {
0297                 items.buttonsBlocked = false;
0298             }
0299         }
0300 
0301 
0302         DialogHelp {
0303             id: dialogHelp
0304             onClose: home()
0305         }
0306 
0307         Bar {
0308             id: bar
0309             level: items.currentLevel + 1
0310             content: BarEnumContent { value: help | home | level | reload }
0311             onHelpClicked: {
0312                 displayDialog(dialogHelp)
0313             }
0314             onPreviousLevelClicked: Activity.previousLevel()
0315             onNextLevelClicked: Activity.nextLevel()
0316             onHomeClicked: activity.home()
0317             onReloadClicked: Activity.initLevel()
0318         }
0319         Bonus {
0320             id: bonus
0321             onWin: {
0322                 if(progressbar.visible)
0323                     Activity.nextLevel();
0324                 else {
0325                     okButton.visible = true;
0326                     items.buttonsBlocked = false;
0327                 }
0328             }
0329         }
0330 
0331         Loader {
0332             id: audioNeededDialog
0333             sourceComponent: GCDialog {
0334                 parent: activity
0335                 isDestructible: false
0336                 message: qsTr("This activity requires sound, so it will play some sounds even if the audio voices or effects are disabled in the main configuration.")
0337                 button1Text: qsTr("Quit")
0338                 button2Text: qsTr("Continue")
0339                 onButton1Hit: activity.home();
0340                 onClose: {
0341                     background.audioDisabled = false;
0342                 }
0343             }
0344             anchors.fill: parent
0345             focus: true
0346             active: background.audioDisabled
0347             onStatusChanged: if (status == Loader.Ready) item.start()
0348         }
0349     }
0350 }