Warning, /education/gcompris/src/activities/grammar_analysis/GrammarAnalysis.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - GrammarAnalysis.qml 0002 * 0003 * Copyright (C) 2022-2023 Bruno ANSELME <be.root@free.fr> 0004 * 0005 * Authors: 0006 * Bruno ANSELME <be.root@free.fr> (Qt Quick native) 0007 * Timothée Giet <animtim@gmail.com> (Graphics and layout refactoring) 0008 * 0009 * SPDX-License-Identifier: GPL-3.0-or-later 0010 */ 0011 import QtQuick 2.12 0012 import QtQuick.Controls 2.12 0013 import GCompris 1.0 0014 0015 import "../../core" 0016 import "grammar_analysis.js" as Activity 0017 import "qrc:/gcompris/src/core/core.js" as Core 0018 0019 ActivityBase { 0020 id: activity 0021 0022 property string grammarMode: "_analysis" // Modified for grammar_classes 0023 readonly property bool translationMode: false // Set this value to true to activate translator's mode 0024 0025 onStart: focus = true 0026 onStop: {} 0027 0028 pageComponent: Image { 0029 id: background 0030 source: "qrc:/gcompris/src/activities/guesscount/resource/backgroundW01.svg" 0031 sourceSize.width: width 0032 sourceSize.height: height 0033 fillMode: Image.PreserveAspectCrop 0034 anchors.fill: parent 0035 signal start 0036 signal stop 0037 0038 // system locale by default 0039 property string locale: "system" 0040 property int baseMargins: 10 * ApplicationInfo.ratio 0041 property int baseRadius: 2 * ApplicationInfo.ratio 0042 property string selectionColor: "#A1CBD9" 0043 0044 Component.onCompleted: { 0045 dialogActivityConfig.initialize() 0046 activity.start.connect(start) 0047 activity.stop.connect(stop) 0048 } 0049 0050 // Add here the QML items you need to access in javascript 0051 QtObject { 0052 id: items 0053 property Item activityPage: activity 0054 property alias background: background 0055 property int currentLevel: activity.currentLevel 0056 property alias bonus: bonus 0057 property alias locale: background.locale 0058 property alias score: score 0059 property GCSfx audioEffects: activity.audioEffects 0060 property bool buttonsBlocked: false 0061 // Qml models 0062 property alias syntaxModel: syntaxModel 0063 property alias datasetModel: datasetModel 0064 property alias goalModel: goalModel 0065 property alias answerModel: answerModel 0066 // Qml main items 0067 property alias wordsFlow: wordsFlow 0068 property alias rowAnswer: rowAnswer 0069 property alias gridGoalTokens: gridGoalTokens 0070 property alias errorRectangle: errorRectangle 0071 // Activity parameters 0072 property int selectedClass: 0 0073 property int selectedBox: 0 0074 property int currentExercise: 0 0075 property alias objective: objective 0076 property bool keyboardNavigation: false 0077 property bool keysOnTokens: true // True when focus is on grammatical tokens else if focus is on words 0078 property var boxIndexes: [] // Array of pairs <word number>-<subclass number (box)> 0079 property alias okButton: okButton 0080 property alias file: file 0081 property alias jsonParser: jsonParser 0082 property alias errors: errors 0083 //--- Debug properties 0084 property bool debugActive: false 0085 property alias inspector: inspector 0086 property alias phrase: phrase 0087 property alias response: response 0088 property string goalStr: "" 0089 property string translationFile: "" // Display translation file's basename 0090 //--- End of debug properties 0091 } 0092 0093 onStart: { Activity.start(items, grammarMode, translationMode) } 0094 onStop: { Activity.stop() } 0095 0096 File { 0097 id: file 0098 onError: console.error("File error: " + msg) 0099 } 0100 0101 JsonParser { 0102 id: jsonParser 0103 onError: errors.text = msg.replace(/invalid\:/,'invalid<br>') 0104 } 0105 0106 ListModel { id: syntaxModel } 0107 ListModel { id: goalModel } 0108 ListModel { id: answerModel } 0109 ListModel { 0110 id: datasetModel 0111 function randPosition() { // choose a random position 0112 return (Math.floor(Math.random() * count)) 0113 } 0114 function shuffleModel() { // shuffle exercises 0115 for (var i = 0 ; i < count; i++) { 0116 move(randPosition(), randPosition(), 1) 0117 } 0118 } 0119 } 0120 0121 // Tutorial section 0122 Image { 0123 id: tutorialScreen 0124 source: "qrc:/gcompris/src/activities/guesscount/resource/backgroundW01.svg" 0125 anchors.fill: parent 0126 sourceSize.width: width 0127 sourceSize.height: height 0128 fillMode: Image.PreserveAspectCrop 0129 visible: true 0130 Tutorial { 0131 id: tutorialSection 0132 useImage: false 0133 tutorialDetails: Activity.tutorialInstructions[grammarMode] 0134 onSkipPressed: { 0135 Activity.initLevel() 0136 tutorialScreen.visible = false 0137 } 0138 } 0139 } 0140 0141 Column { // invisible column to get longest word from the class names 0142 id: tokenTextSizeRef 0143 visible: false 0144 width: childrenRect.width 0145 Repeater { 0146 model: goalModel 0147 delegate: GCText { 0148 fontSize: tinySize 0149 text: wordClass 0150 } 0151 } 0152 } 0153 0154 // Main section 0155 Item { 0156 id: mainArea 0157 anchors.top: parent.top 0158 anchors.bottom: scoreButtonContainer.top 0159 anchors.left: parent.left 0160 anchors.right: parent.right 0161 anchors.margins: background.baseMargins 0162 visible: !tutorialScreen.visible 0163 Column { 0164 anchors.top: parent.top 0165 anchors.horizontalCenter: parent.horizontalCenter 0166 width: parent.width 0167 height: parent.height 0168 spacing: background.baseMargins 0169 Rectangle { 0170 id: objectiveContainer 0171 width: objective.paintedWidth + background.baseMargins * 2 0172 height: objective.paintedHeight + background.baseMargins 0173 color: "#80FFFFFF" 0174 radius: background.baseRadius 0175 anchors.horizontalCenter: parent.horizontalCenter 0176 GCText { // Exercise's objective 0177 id: objective 0178 fontSize: regularSize 0179 fontSizeMode: Text.Fit 0180 width: mainArea.width - background.baseMargins * 2 0181 height: mainArea.height * 0.2 - background.baseMargins 0182 horizontalAlignment: Text.AlignHCenter 0183 verticalAlignment: Text.AlignVCenter 0184 anchors.horizontalCenter: parent.horizontalCenter 0185 anchors.verticalCenter: parent.verticalCenter 0186 wrapMode: Text.WordWrap 0187 } 0188 } 0189 Rectangle { // Display grammatical classes (goal) 0190 id: goalTokensContainer 0191 color: "#F0F0F0" 0192 anchors.horizontalCenter: parent.horizontalCenter 0193 width: gridGoalTokens.width + background.baseMargins 0194 height: gridGoalTokens.height + background.baseMargins 0195 radius: background.baseRadius 0196 focus: true 0197 z: 2 0198 Rectangle { 0199 z: -1 0200 color: background.selectionColor 0201 radius: background.baseRadius 0202 visible: items.keyboardNavigation && items.keysOnTokens 0203 anchors.centerIn: parent 0204 width: parent.width + background.baseMargins 0205 height: parent.height + background.baseMargins 0206 } 0207 Grid { 0208 id: gridGoalTokens 0209 anchors.centerIn: parent 0210 columns: mainArea.width / tokenWidth 0211 layoutDirection: (Core.isLeftToRightLocale(items.locale)) ? Qt.LeftToRight : Qt.RightToLeft 0212 0213 property real tokenWidth: Math.max(75 * ApplicationInfo.ratio, tokenTextSizeRef.width) 0214 property real tokenHeight: columns < goalModel.count ? 40 * ApplicationInfo.ratio : 60 * ApplicationInfo.ratio 0215 0216 Repeater { 0217 model: goalModel 0218 delegate: GrammarToken { 0219 width: gridGoalTokens.tokenWidth 0220 height: gridGoalTokens.tokenHeight 0221 classCode: code 0222 className: wordClass 0223 svgName: image 0224 } 0225 } 0226 } 0227 } 0228 Item { 0229 id: wordsArea 0230 width: mainArea.width 0231 height: mainArea.height - objectiveContainer.height - goalTokensContainer.height - background.baseMargins * 2 0232 0233 property real itemHeight: Math.min(40 * ApplicationInfo.ratio, height * 0.2) 0234 property bool isSmallHeight: itemHeight < 30 * ApplicationInfo.ratio 0235 0236 Rectangle { // Display sentence 0237 color: "#F0F0F0" 0238 width: parent.width 0239 height: wordsFlow.height 0240 radius: background.baseRadius 0241 Rectangle { 0242 z: -1 0243 color: background.selectionColor 0244 radius: background.baseRadius 0245 visible: items.keyboardNavigation && !items.keysOnTokens 0246 anchors.centerIn: parent 0247 width: parent.width + background.baseMargins 0248 height: parent.height + background.baseMargins 0249 } 0250 Flow { 0251 id: wordsFlow 0252 width: parent.width - background.baseMargins * 2 0253 spacing: 0 0254 leftPadding: background.baseMargins 0255 rightPadding: background.baseMargins 0256 anchors.verticalCenter: parent.verticalCenter 0257 layoutDirection: (Core.isLeftToRightLocale(items.locale)) ? Qt.LeftToRight : Qt.RightToLeft 0258 Repeater { 0259 id: rowAnswer 0260 model: answerModel 0261 delegate: WordAndClass { 0262 expected: code 0263 wordText: word 0264 proposition: prop 0265 startPos: startCount 0266 } 0267 } 0268 } 0269 ErrorRectangle { 0270 id: errorRectangle 0271 anchors.fill: parent 0272 radius: parent.radius 0273 imageSize: okButton.width 0274 function releaseControls() { items.buttonsBlocked = false; } 0275 } 0276 } 0277 GCText { // Error text 0278 id: errors 0279 color: "red" 0280 style: Text.Outline 0281 styleColor: "white" 0282 fontSize: tinySize 0283 anchors.horizontalCenter: parent.horizontalCenter 0284 } 0285 } 0286 } 0287 MouseArea { 0288 // used to block all mouse input on activity interface execpt the OK button 0289 anchors.fill: parent 0290 enabled: items.buttonsBlocked 0291 } 0292 } 0293 0294 DialogChooseLevel { 0295 id: dialogActivityConfig 0296 currentActivity: activity.activityInfo 0297 0298 onSaveData: { 0299 levelFolder = dialogActivityConfig.chosenLevels 0300 currentActivity.currentLevels = dialogActivityConfig.chosenLevels 0301 ApplicationSettings.setCurrentLevels(currentActivity.name, dialogActivityConfig.chosenLevels) 0302 } 0303 onLoadData: { 0304 if(activityData && activityData["locale"]) { 0305 background.locale = Core.resolveLocale(activityData["locale"]); 0306 } 0307 else { 0308 background.locale = Core.resolveLocale(background.locale); 0309 } 0310 } 0311 onClose: { 0312 home() 0313 } 0314 onStartActivity: { 0315 background.start() 0316 } 0317 } 0318 DialogHelp { 0319 id: dialogHelp 0320 onClose: home() 0321 } 0322 0323 Bar { 0324 id: bar 0325 level: items.currentLevel + 1 0326 content: BarEnumContent { value: tutorialScreen.visible ? help | home : help | home | level | activityConfig } 0327 onHelpClicked: displayDialog(dialogHelp) 0328 onActivityConfigClicked: displayDialog(dialogActivityConfig) 0329 onPreviousLevelClicked: Activity.previousLevel() 0330 onNextLevelClicked: Activity.nextLevel() 0331 onHomeClicked: activity.home() 0332 } 0333 0334 Item { 0335 id: scoreButtonContainer 0336 visible: !tutorialScreen.visible 0337 width: score.width + background.baseMargins + okButton.width 0338 height: okButton.height 0339 anchors.horizontalCenter: parent.horizontalCenter 0340 anchors.bottom: background.bottom 0341 anchors.bottomMargin: 1.5 * bar.height 0342 0343 BarButton { 0344 id: okButton 0345 source: "qrc:/gcompris/src/core/resource/bar_ok.svg" 0346 width: 60 * ApplicationInfo.ratio 0347 anchors.right: parent.right 0348 anchors.bottom: parent.bottom 0349 sourceSize.width: width 0350 onClicked: Activity.checkResult() 0351 mouseArea.enabled: !items.buttonsBlocked 0352 } 0353 0354 Score { 0355 id: score 0356 numberOfSubLevels: items.datasetModel.count 0357 currentSubLevel: items.currentExercise 0358 anchors.left: parent.left 0359 anchors.verticalCenter: parent.verticalCenter 0360 anchors.margins: 0 0361 anchors.bottom: undefined 0362 anchors.top: undefined 0363 anchors.right: undefined 0364 visible: !tutorialScreen.visible 0365 onStop: Activity.nextSubLevel() 0366 } 0367 } 0368 0369 Bonus { 0370 id: bonus 0371 Component.onCompleted: win.connect(Activity.nextLevel) 0372 } 0373 0374 Keys.onPressed: Activity.handleKeys(event) 0375 0376 //--- Debugging zone. 0377 Text { 0378 id: hideDebug 0379 text: "Alt+Left and Alt+Right to change exercise\nCtrl+Alt+Return to flip debug informations" 0380 anchors.top: scoreButtonContainer.bottom 0381 anchors.right: parent.right 0382 visible: translationMode 0383 } 0384 Column { 0385 id: infoView 0386 anchors.bottom: scoreButtonContainer.bottom 0387 visible: items.debugActive 0388 spacing: 5 0389 Text { 0390 width: 200 0391 height: 80 0392 text: "Activity: %1\nLocale: %2\nTranslation file: %3\nExercise: %4/%5\nGoal: %6".arg(activityInfo.title).arg(items.locale).arg(items.translationFile).arg(items.currentExercise + 1).arg(datasetModel.count).arg(items.goalStr) 0393 } 0394 Text { 0395 id: phrase 0396 width: 200 0397 height: 16 0398 } 0399 Text { 0400 id: response 0401 width: 200 0402 height: 16 0403 } 0404 } 0405 0406 Rectangle { 0407 id: inspector 0408 property alias message: msg.text 0409 property bool shown: false 0410 anchors.top: parent.top 0411 anchors.left: parent.left 0412 width: shown ? msg.contentWidth + 10 : 70 0413 height: shown ? msg.contentHeight + 4 : 18 0414 color: "white" 0415 opacity: 0.5 0416 radius: 5 0417 visible: items.debugActive 0418 Text { 0419 id: msg 0420 anchors.fill: parent 0421 text: "Debug area" 0422 clip: true 0423 } 0424 MouseArea { 0425 anchors.fill: parent 0426 hoverEnabled: true 0427 onClicked: { parent.shown = !parent.shown } 0428 onEntered: { inspector.opacity = 1.0 } 0429 onExited: { inspector.opacity = 0.5 } 0430 } 0431 } 0432 //--- End of debugging zone. 0433 } 0434 }