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

0001 /* GCompris - GraduatedLineRead.qml
0002  *
0003  * SPDX-FileCopyrightText: 2023 Bruno ANSELME <be.root@free.fr>
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 import QtQuick 2.12
0007 import GCompris 1.0
0008 import "../../core"
0009 import "qrc:/gcompris/src/core/core.js" as Core
0010 import "graduated_line_read.js" as Activity
0011 
0012 ActivityBase {
0013     id: activity
0014     property string activityMode: "tick2number" // Possible values: tick2number, number2tick
0015     property string instruction: qsTr("Find the requested number.")
0016 
0017     onStart: focus = true
0018     onStop: {}
0019 
0020     pageComponent: Image {
0021         id: background
0022         source: "qrc:/gcompris/src/activities/chess/resource/background-wood.svg"
0023         anchors.fill: parent
0024         fillMode: Image.PreserveAspectCrop
0025         sourceSize.height: height
0026         signal start
0027         signal stop
0028 
0029         Component.onCompleted: {
0030             activity.start.connect(start)
0031             activity.stop.connect(stop)
0032         }
0033 
0034         // Add here the QML items you need to access in javascript
0035         QtObject {
0036             id: items
0037             property Item main: activity.main
0038             property alias background: background
0039             property int currentLevel: activity.currentLevel
0040             property int currentSubLevel: 0
0041             property int numberOfSubLevel: 0
0042             property alias bar: bar
0043             property alias bonus: bonus
0044             property alias score: score
0045             property alias numPad: numPad
0046             property var levels: activity.datasetLoader.data
0047             property GCSfx audioEffects: activity.audioEffects
0048 
0049             property int solutionGrad: 0                // Solution's graduation
0050             property int orientation: Qt.LeftToRight      // Updated with ApplicationSettings in start() function
0051 
0052             property alias ruler: ruler
0053             property alias cursor: cursor
0054             property alias rulerModel: rulerModel
0055             property alias leftLimit: leftLimit
0056             property alias rightLimit: rightLimit
0057             property string answer: ""
0058             property alias errorRectangle: errorRectangle
0059             property bool buttonsBlocked: false
0060         }
0061 
0062         property int baseMargins: 10 * ApplicationInfo.ratio
0063 
0064         onStart: { Activity.start(items, activityMode) }
0065         onStop: { Activity.stop() }
0066 
0067         Rectangle {
0068             id: instructionArea
0069             opacity: 1
0070             radius: background.baseMargins
0071             color: "#373737"
0072             height: 40 * ApplicationInfo.ratio
0073             width: Math.min(320 * ApplicationInfo.ratio, parent.width - 2 * background.baseMargins)
0074             anchors.horizontalCenter: parent.horizontalCenter
0075             anchors.top: parent.top
0076             anchors.topMargin: background.baseMargins
0077 
0078             GCText {
0079                 id: instruction
0080                 wrapMode: TextEdit.WordWrap
0081                 horizontalAlignment: Text.AlignHCenter
0082                 verticalAlignment: Text.AlignVCenter
0083                 height: parent.height - background.baseMargins
0084                 width: parent.width - 2 * background.baseMargins
0085                 fontSizeMode: Text.Fit
0086                 color: 'white'
0087                 anchors.centerIn: instructionArea
0088                 text: activity.instruction
0089             }
0090         }
0091 
0092         Item {
0093             id: layoutArea
0094             anchors.top: instructionArea.bottom
0095             anchors.bottom: background.bottom
0096             anchors.bottomMargin: 1.2 * bar.height
0097             anchors.left: background.left
0098             anchors.right: background.right
0099             anchors.margins: background.baseMargins
0100         }
0101 
0102         ListModel { id: rulerModel }
0103 
0104         Rectangle {
0105             id: rulerView
0106             anchors.top: layoutArea.top
0107             anchors.left: layoutArea.left
0108             anchors.right: layoutArea.right
0109             height: Math.min(120 * ApplicationInfo.ratio, layoutArea.height * 0.4)
0110             color: "#e9e9e9"
0111             radius: background.baseMargins
0112             property real rulerWidth: rulerView.width - leftLimit.width
0113             property real rulerModelWidth: ruler.width / (rulerModel.count - 1)
0114             Column {
0115                 id: rulerViewColumn
0116                 width: rulerView.rulerWidth
0117                 height: parent.height - background.baseMargins
0118                 anchors.horizontalCenter: parent.horizontalCenter
0119                 anchors.horizontalCenterOffset: rulerView.rulerModelWidth * -0.5
0120                 anchors.top: parent.top
0121                 anchors.topMargin: background.baseMargins
0122                 Row {
0123                     id: cursor
0124                     z: 100
0125                     width: parent.width
0126                     height: parent.height * 0.3
0127                     anchors.horizontalCenter: parent.horizontalCenter
0128                     layoutDirection: items.orientation
0129                     Repeater {
0130                         model: rulerModel
0131                         delegate : Item {
0132                             property int value: value_
0133                             property bool hidden: (index !== items.solutionGrad)
0134                             property alias textValue: txt.text
0135                             width: rulerView.rulerModelWidth
0136                             height: parent.height
0137                             opacity: hidden ? 0.0 : 1.0
0138                             Image {
0139                                 visible: activity.activityMode === "number2tick"
0140                                 source: "qrc:/gcompris/src/activities/graduated_line_read/resource/arrow.svg"
0141                                 anchors.centerIn: parent
0142                                 anchors.verticalCenterOffset: 5 * ApplicationInfo.ratio
0143                                 height: parent.height
0144                                 width: height
0145                                 sourceSize.width: height
0146                             }
0147                             Rectangle {
0148                                 visible: activity.activityMode === "tick2number" ? true : txt.text != ""
0149                                 anchors.centerIn: parent
0150                                 anchors.verticalCenterOffset: txt.anchors.verticalCenterOffset
0151                                 height: parent.height
0152                                 width: 90 * ApplicationInfo.ratio
0153                                 radius: height * 0.1
0154                                 color: "white"
0155                                 border.color: "#633E0C"
0156                                 border.width:  2 * ApplicationInfo.ratio
0157                             }
0158                             GCText {
0159                                 id: txt
0160                                 anchors.centerIn: parent
0161                                 anchors.verticalCenterOffset: 2 * ApplicationInfo.ratio
0162                                 height: parent.height * 0.9
0163                                 width: 80 * ApplicationInfo.ratio
0164                                 horizontalAlignment: Text.AlignHCenter
0165                                 verticalAlignment: Text.AlignVCenter
0166                                 text: ""
0167                                 fontSize: mediumSize
0168                                 fontSizeMode: Text.Fit
0169                                 color: "#373737"
0170                             }
0171                         }
0172                     }
0173                 }
0174 
0175                 Row {
0176                     id: ruler
0177                     width: rulerView.rulerWidth
0178                     height: parent.height
0179                     layoutDirection: items.orientation
0180                     anchors.horizontalCenter: parent.horizontalCenter
0181                     Repeater {
0182                         model: rulerModel
0183                         delegate : Item {
0184                             property int value: value_
0185                             property int thickness: thickness_
0186                             width: rulerView.rulerModelWidth
0187                             height: 100
0188                             transform: Scale { origin.x: width / 2; xScale: (items.orientation === Qt.LeftToRight) ? 1 : -1 }
0189 
0190                             Rectangle {     // Line between graduations
0191                                 width: (index && (index !== (rulerModel.count - 1))) ? parent.width : parent.width / 2
0192                                 height: Activity.segmentThickness * ApplicationInfo.ratio
0193                                 anchors.verticalCenter: parent.verticalCenter
0194                                 anchors.left: (index) ? parent.left : undefined
0195                                 anchors.right: (!index) ? parent.right : undefined
0196                                 color: "#c27a33"
0197                             }
0198                             Rectangle {     // vertical graduation
0199                                 width: thickness * ApplicationInfo.ratio
0200                                 height: ((!index) || (index === (rulerModel.count - 1)) || (index === items.solutionGrad))
0201                                 ?  parent.height : (parent.height / 2)
0202                                 anchors.centerIn: parent
0203                                 color: (index === items.solutionGrad) ? "#633E0C" : "#c27a33"
0204                                 radius: (index === items.solutionGrad) ? 0 : width * 0.5
0205                             }
0206                         }
0207                     }
0208                 }
0209             }
0210         }
0211 
0212         Rectangle {
0213             anchors.centerIn: leftLimit
0214             width: background.baseMargins
0215             height: leftLimit.paintedHeight
0216             color: "#e9e9e9"
0217         }
0218 
0219         GCText {
0220             id: leftLimit
0221             width: 80 * ApplicationInfo.ratio
0222             anchors.left: layoutArea.left
0223             anchors.bottom: rulerView.bottom
0224             horizontalAlignment: Text.AlignHCenter
0225             verticalAlignment: Text.AlignVCenter
0226             fontSize: smallSize
0227             fixFontSize: true
0228         }
0229 
0230         Rectangle {
0231             anchors.centerIn: rightLimit
0232             width: background.baseMargins
0233             height: rightLimit.paintedHeight
0234             color: "#e9e9e9"
0235         }
0236 
0237         GCText {
0238             id: rightLimit
0239             width: leftLimit.width
0240             anchors.right: layoutArea.right
0241             anchors.bottom: rulerView.bottom
0242             horizontalAlignment: Text.AlignHCenter
0243             verticalAlignment: Text.AlignVCenter
0244             fontSize: smallSize
0245             fixFontSize: true
0246         }
0247 
0248         ErrorRectangle {
0249             id: errorRectangle
0250             width: activityMode === "tick2number" ? 90 * ApplicationInfo.ratio : 0
0251             height: cursor.height
0252             property real cursorOffset: (rulerView.rulerModelWidth - width) * 0.5
0253             x: rulerView.x + rulerViewColumn.x + cursor.x + rulerView.rulerModelWidth * items.solutionGrad + cursorOffset
0254             y: rulerView.y + rulerViewColumn.y + cursor.y + 2 * ApplicationInfo.ratio
0255             radius: height * 0.1
0256             imageSize: height * 1.2
0257             function releaseControls() {
0258                 items.buttonsBlocked = false;
0259             }
0260         }
0261 
0262         ListModel {
0263             id: padModel
0264             ListElement { label: "7";  key: Qt.Key_7 }
0265             ListElement { label: "8";  key: Qt.Key_8 }
0266             ListElement { label: "9";  key: Qt.Key_9 }
0267             ListElement { label: "4";  key: Qt.Key_4 }
0268             ListElement { label: "5";  key: Qt.Key_5 }
0269             ListElement { label: "6";  key: Qt.Key_6 }
0270             ListElement { label: "1";  key: Qt.Key_1 }
0271             ListElement { label: "2";  key: Qt.Key_2 }
0272             ListElement { label: "3";  key: Qt.Key_3 }
0273             ListElement { label: "<<";  key: Qt.Key_Backspace }
0274             ListElement { label: "0";  key: Qt.Key_0 }
0275             ListElement { label: "C";  key: Qt.Key_Delete }
0276         }
0277 
0278         Row {
0279             id: tools
0280             width: childrenRect.width
0281             height: layoutArea.height - rulerView.height - anchors.topMargin
0282             anchors.top: rulerView.bottom
0283             anchors.topMargin: background.baseMargins * 2
0284             anchors.horizontalCenter: parent.horizontalCenter
0285             spacing: background.baseMargins
0286             Image {
0287                 id: leftButton
0288                 source: 'qrc:/gcompris/src/core/resource/arrow_left.svg'
0289                 smooth: true
0290                 width: Math.min(70 * ApplicationInfo.ratio, layoutArea.width * 0.15)
0291                 height: width
0292                 sourceSize.width: width
0293                 sourceSize.height: width
0294                 fillMode: Image.PreserveAspectFit
0295                 visible: (activityMode === "number2tick")
0296                 MouseArea {
0297                     id: leftArea
0298                     anchors.fill: parent
0299                     hoverEnabled: true
0300                     enabled: !items.buttonsBlocked
0301                     onContainsMouseChanged: leftButton.scale = (containsMouse) ? 1.1 : 1.0
0302                     onClicked: (items.orientation === Qt.LeftToRight) ? Activity.moveLeft() : Activity.moveRight()
0303                 }
0304                 Behavior on scale {
0305                     PropertyAnimation {
0306                         target: leftButton
0307                         properties: "scale"
0308                         duration: 100
0309                     }
0310                 }
0311             }
0312 
0313             Rectangle {
0314                 width: 80 * ApplicationInfo.ratio
0315                 height: 40 * ApplicationInfo.ratio
0316                 color: "white"
0317                 radius: background.baseMargins
0318                 anchors.verticalCenter: leftButton.verticalCenter
0319                 visible: (activityMode === "number2tick")
0320                 GCText {
0321                     anchors.centerIn: parent
0322                     width: parent.width * 0.9
0323                     height: parent.height * 0.9
0324                     horizontalAlignment: Text.AlignHCenter
0325                     verticalAlignment: Text.AlignVCenter
0326                     fontSizeMode: Text.Fit
0327                     fontSize: mediumSize
0328                     text: items.answer
0329                 }
0330             }
0331 
0332             Image {
0333                 id: rightButton
0334                 source: 'qrc:/gcompris/src/core/resource/arrow_right.svg'
0335                 smooth: true
0336                 width: leftButton.width
0337                 height: leftButton.width
0338                 sourceSize.width: leftButton.width
0339                 sourceSize.height: leftButton.width
0340                 fillMode: Image.PreserveAspectFit
0341                 visible: (activityMode === "number2tick")
0342                 MouseArea {
0343                     id: rightArea
0344                     anchors.fill: parent
0345                     hoverEnabled: true
0346                     enabled: !items.buttonsBlocked
0347                     onContainsMouseChanged: rightButton.scale = (containsMouse) ? 1.1 : 1.0
0348                     onClicked: (items.orientation === Qt.LeftToRight) ? Activity.moveRight() : Activity.moveLeft()
0349                 }
0350                 Behavior on scale {
0351                     PropertyAnimation {
0352                         target: rightButton
0353                         properties: "scale"
0354                         duration: 100
0355                     }
0356                 }
0357             }
0358 
0359             GridView {
0360                 id: numPad
0361                 width: Math.ceil(3 * cellWidth)
0362                 height: Math.ceil(4 * cellHeight)
0363                 cellWidth: Math.min(60 * ApplicationInfo.ratio, layoutArea.width / 9)
0364                 cellHeight: Math.min(40 * ApplicationInfo.ratio, tools.height / 4)
0365                 interactive: false
0366                 visible: (activityMode === "tick2number")
0367                 model: padModel
0368 
0369                 delegate: Rectangle {
0370                     id: numKey
0371                     width: numPad.cellWidth - 2 * ApplicationInfo.ratio
0372                     height: numPad.cellHeight - 2 * ApplicationInfo.ratio
0373                     anchors.margins: ApplicationInfo.ratio
0374                     color: numArea.containsMouse ? "#C0C0C0" : "#E5E5E5"
0375                     border.color: "#808080"
0376                     border.width: ApplicationInfo.ratio
0377                     radius: height * 0.1
0378                     GCText {
0379                         anchors.centerIn: parent
0380                         width: parent.width * 0.9
0381                         height: parent.height * 0.9
0382                         horizontalAlignment: Text.AlignHCenter
0383                         verticalAlignment: Text.AlignVCenter
0384                         fontSizeMode: Text.Fit
0385                         fontSize: mediumSize
0386                         text: label
0387                     }
0388                     MouseArea {
0389                         id: numArea
0390                         anchors.fill: parent
0391                         hoverEnabled: true
0392                         enabled: !items.buttonsBlocked
0393                         onClicked: Activity.handleKeys(key)
0394                     }
0395                     states: [
0396                         State {
0397                             name: ""
0398                             PropertyChanges {
0399                                 target: numKey
0400                                 color: numArea.containsMouse ? "#C0C0C0" : "#E5E5E5"
0401                             }
0402                         },
0403                         State {
0404                             name: "pressed"
0405                             PropertyChanges {
0406                                 target: numKey
0407                                 color: "#999"
0408                             }
0409                         }
0410                     ]
0411                     transitions: [
0412                         Transition {
0413                             to: "pressed"
0414                             SequentialAnimation {
0415                                 ScriptAction { script: audioEffects.play('qrc:/gcompris/src/core/resource/sounds/audioclick.wav') }
0416                                 ColorAnimation { duration: 100 }
0417                                 ScriptAction { script: state = "" }
0418                             }
0419                         }
0420                     ]
0421                     Component.onCompleted: Activity.mapToPad[key] = index
0422                 }
0423             }
0424         }
0425 
0426         DialogChooseLevel {
0427             id: dialogActivityConfig
0428             currentActivity: activity.activityInfo
0429 
0430             onSaveData: {
0431                 levelFolder = dialogActivityConfig.chosenLevels
0432                 currentActivity.currentLevels = dialogActivityConfig.chosenLevels
0433                 ApplicationSettings.setCurrentLevels(currentActivity.name, dialogActivityConfig.chosenLevels)
0434             }
0435             onClose: {
0436                 home()
0437             }
0438             onStartActivity: {
0439                 background.stop()
0440                 background.start()
0441             }
0442         }
0443 
0444         DialogHelp {
0445             id: dialogHelp
0446             onClose: home()
0447         }
0448 
0449         Score {
0450             id: score
0451             numberOfSubLevels: items.numberOfSubLevel
0452             currentSubLevel: items.currentSubLevel
0453             anchors.top: undefined
0454             anchors.bottom: background.bottom
0455             anchors.bottomMargin: bar.height * 1.5
0456             anchors.right: background.right
0457             anchors.rightMargin: background.baseMargins
0458             onStop: Activity.nextSubLevel()
0459         }
0460 
0461         Bar {
0462             id: bar
0463             level: items.currentLevel + 1
0464             content: BarEnumContent { value: help | home | level | activityConfig }
0465             onHelpClicked: displayDialog(dialogHelp)
0466             onActivityConfigClicked: displayDialog(dialogActivityConfig)
0467             onPreviousLevelClicked: Activity.previousLevel()
0468             onNextLevelClicked: Activity.nextLevel()
0469             onHomeClicked: activity.home()
0470         }
0471 
0472         BarButton {
0473             id: okButton
0474             source: "qrc:/gcompris/src/core/resource/bar_ok.svg"
0475             width: Math.min(70 * ApplicationInfo.ratio, tools.height * 0.4)
0476             height: width
0477             sourceSize.height: width
0478             sourceSize.width: width
0479             anchors.bottom: score.top
0480             anchors.bottomMargin: background.baseMargins
0481             anchors.horizontalCenter: score.horizontalCenter
0482             onClicked: Activity.checkResult()
0483             visible: (items.cursor.children[items.solutionGrad].textValue !== "") || (activityMode === "number2tick")
0484             mouseArea.enabled: !items.buttonsBlocked
0485         }
0486 
0487         Bonus {
0488             id: bonus
0489             Component.onCompleted: win.connect(Activity.nextLevel)
0490         }
0491 
0492         Keys.onPressed: Activity.handleEvents(event)
0493     }
0494 
0495 }