diff --git a/src/activities/numeration_weights_integer/Numeration_weights_integer.qml b/src/activities/numeration_weights_integer/Numeration_weights_integer.qml index 9bb46b398..c4127630e 100644 --- a/src/activities/numeration_weights_integer/Numeration_weights_integer.qml +++ b/src/activities/numeration_weights_integer/Numeration_weights_integer.qml @@ -1,664 +1,664 @@ /* GCompris - Share.qml * * Copyright (C) 2019 Emmanuel Charruau * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ // TODO: ne valider que si les poids sont dans la bonne case // TODO: ajouter des niveaux pour pouvoir le faire tester par un élève // TODO: fix error when removing a class dragging it // TODO: give new number only when bonus is finished // TODO: remove cellsize // TODO: is it possible to have a vertical mode? If not remove everything related to vertical mode // TODO: remove settings in bar menu -import QtQuick 2.6 +import QtQuick 2.13 import GCompris 1.0 import QtQuick.Layouts 1.3 import QtQuick.Controls 1.5 import QtQml.Models 2.1 import "../../core" import "numeration_weights_integer.js" as Activity ActivityBase { id: activity onStart: focus = true onStop: {} pageComponent: Rectangle { id: background anchors.fill: parent color: "#ffffb3" signal start signal stop Component.onCompleted: { dialogActivityConfig.getInitialConfiguration() activity.start.connect(start) activity.stop.connect(stop) } // Add here the QML items you need to access in javascript QtObject { id: items property Item main: activity.main property alias background: background property alias mainZoneArea: mainZoneArea property alias bar: bar property alias bonus: bonus property alias instruction: instruction property alias warningRectangle: warningRectangle property alias dataset: dataset property alias numberClassListModel: numberClassListModel property alias numberClassDragListModel: numberClassDragListModel property alias numberWeightDragListModel: numberWeightDragListModel property alias numberClassTypeModel: numberClassTypeModel property alias leftWidget: leftWidget property alias progressBar: progressBar property alias numberClassDropAreaRepeater: numberClassDropAreaRepeater property alias classNameListView: classNameListView property int barHeightAddon: ApplicationSettings.isBarHidden ? 1 : 3 property int cellSize: Math.min(background.width / 11, background.height / (9 + barHeightAddon)) property var levels: activity.datasetLoader.item.data property alias numberToConvertRectangle: numberToConvertRectangle } Loader { id: dataset asynchronous: false } onStart: { Activity.start(items) } onStop: { Activity.stop() } property bool vert: background.width >= background.height //mainZone DropArea { id: mainZoneArea width: background.vert ? background.width - leftWidget.width - 40 : background.width - 40 height: ApplicationSettings.isBarHidden ? background.height : background.vert ? background.height - (bar.height * 1.1) : background.height - (bar.height * 1.1) - leftWidget.height anchors { top: background.vert ? background.top : leftWidget.bottom left: background.vert ? leftWidget.right : parent.left leftMargin: 20 } keys: "NumberClassKey" //shows/hides the objective/instruction MouseArea { anchors.fill: mainZoneArea onClicked: instruction.show() } Rectangle { id: mainZoneAreaDropRectangleVisualisation anchors.fill: parent color: "pink" } onDropped: { console.log("Here is should also drop when dragging with animation, it does only with mouse area dragging") var className = drag.source.name drag.source.dragEnabled = false Activity.appendClassNameColumn(className, drag.source, false) } Rectangle { id: topBanner height: mainZoneArea.height / 10 width: mainZoneArea.width anchors { left: mainZoneArea.left top: mainZoneArea.top } color: "green" Rectangle { id: numberToConvertRectangle anchors.fill: numberToConvertRectangleTxt color: "blue" opacity: 0.8 property alias text: numberToConvertRectangleTxt.text } //display number to convert GCText { id: numberToConvertRectangleTxt height: parent.height width: parent.width / 3 anchors { left: numberToConvertRectangle.left top: numberToConvertRectangle.top } opacity: numberToConvertRectangle.opacity //z: instruction.z fontSize: background.vert ? regularSize : smallSize color: "white" style: Text.Outline styleColor: "black" horizontalAlignment: Text.AlignHCenter wrapMode: TextEdit.WordWrap } ProgressBar { id: progressBar height: parent.height width: parent.width / 3 property int percentage: 0 maximumValue: 100 visible: true //!items.isTutorialMode anchors { bottom: parent.bottom right: parent.right rightMargin: 40 } GCText { anchors.centerIn: parent fontSize: mediumSize font.bold: true color: "black" //: The following translation represents percentage. text: qsTr("%1%").arg(parent.value) z: 2 } } } //store strings Integer and Decimal to display in numeration table header ListModel { id: numberClassTypeModel } Rectangle { id: numberClassTypeHeader width: mainZoneArea.width height: mainZoneArea.height / 20 anchors.top: topBanner.bottom anchors.left: parent.left anchors.right: parent.right border.color: "blue" border.width: 1 ListView { id: numberClassTypeHeaderListView anchors { fill: parent} model: numberClassTypeModel orientation: ListView.Horizontal delegate: Rectangle { width: numberClassTypeModel.get(index).numberClassTypeHeaderWidth height: numberClassTypeHeader.height border.width: 1 border.color: "black" color: "lightsteelblue" radius: 2 GCText { id: numberClassHeaderCaption anchors.fill: parent anchors.bottom: parent.bottom fontSizeMode: Text.Fit color: "black" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: numberClassTypeModel.get(index).numberClassType visible: numberClassTypeModel.get(index).numberClassTypeHeaderWidth === 0 ? false : true } } } } Rectangle { id: numberClassHeaders width: mainZoneArea.width height: mainZoneArea.height / 10 anchors.top: numberClassTypeHeader.bottom anchors.left: parent.left anchors.right: parent.right border.color: "red" border.width: 1 GCText { id: numberClassHeadersRectangleAdvice height: parent.height width: parent.width anchors { horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter } opacity: visualModel.count === 0 ? 1 : 0 fontSizeMode: Text.Fit color: "black" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: qsTr("Drag here the class numbers") } ListView { id: classNameListView anchors { fill: parent} model: visualModel orientation: ListView.Horizontal interactive: false cacheBuffer: 50 } DelegateModel { id: visualModel model: numberClassListModel delegate: nnumberClassHeaderElement //Qt.createComponent("NumberClassHeaderElement.qml") //ask johnny for some help there } } Component { // ? what to do when removed element ? TypeError: Cannot read property 'misplaced' of undefined id: nnumberClassHeaderElement MouseArea { id: dragArea property bool held: false width: mainZoneArea.width / numberClassListModel.count height: numberClassHeaders.height drag.target: held ? content : undefined drag.axis: Drag.XAxis onPressed: held = true onReleased: { if ((content.x < leftWidget.width) && held) //? don't understand why I have a content.x = 0 when held is not true, this point needs to be cleared { console.log("index className element",index) numberClassListModel.get(index).element_src.dragEnabled = true numberClassListModel.remove(index,1) Activity.updateIntegerAndDecimalHeaderWidth() } held = false } Rectangle { id: content anchors { horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter } width: mainZoneArea.width / numberClassListModel.count height: numberClassHeaders.height / 1.5 border.width: 1 //FIXME: when removing an element of NumberClassList model border color is stilll asked border.color: numberClassListModel.get(index).misplaced === true ? "red" : "lightsteelblue" color: dragArea.held ? "lightsteelblue" : "white" Behavior on color { ColorAnimation { duration: 100 } } radius: 2 Drag.active: dragArea.held Drag.source: dragArea Drag.hotSpot.x: width / 2 Drag.hotSpot.y: height / 2 states: State { when: dragArea.held ParentChange { target: content; parent: root } AnchorChanges { target: content anchors { horizontalCenter: undefined; verticalCenter: undefined } } } GCText { id: numberClassHeaderCaption anchors.fill: parent anchors.bottom: parent.bottom fontSizeMode: Text.Fit color: "black" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: numberClassListModel.get(index).name //here there a problem when removing a number class z: 100 } } DropArea { anchors { fill: parent; margins: 10 } onEntered: { console.log("dragArea.DelegateModel.itemsIndex",dragArea.DelegateModel.itemsIndex) console.log("classNameListView.count",classNameListView.count) //move class name columns except the decimal part which stays always on the last position if (dragArea.DelegateModel.itemsIndex < classNameListView.count - 1) { numberClassListModel.move(drag.source.DelegateModel.itemsIndex, dragArea.DelegateModel.itemsIndex,1) } } } } } RowLayout { id: numberClassDropAreasGridLayout anchors.top: numberClassHeaders.bottom width: parent.width height: parent.height - topBanner.height - numberClassHeaders.height - numberClassTypeHeader.height spacing: 10 Repeater { id: numberClassDropAreaRepeater model: numberClassListModel NumberClassDropArea { id: numberClassDropAreaElement //property alias numberWeightDragListModel: activity.background.numberWeightDragListModel //? className: name //name comes from numberClassListModel Layout.fillHeight: true Layout.fillWidth: true Layout.minimumWidth: 50 Layout.preferredWidth: 100 } } } Tutorial { id: tutorialSection tutorialText.anchors.top: undefined tutorialText.anchors.bottom: tutorialSection.bottom tutorialText.anchors.margins: tutorialSection.tutorialText.height tutorialDetails: Activity.tutorialInstructions useImage: false onSkipPressed: { Activity.initLevel() tutorialImage.visible = false } } } ListModel { id: numberClassListModel } ListModel { id: numberClassDragListModel } ListModel { id: numberWeightDragListModel } //instruction rectangle Rectangle { id: instruction anchors.fill: instructionTxt opacity: 0.8 radius: 10 border.width: 2 z: 10 border.color: "black" gradient: Gradient { GradientStop { position: 0.0; color: "#000" } GradientStop { position: 0.9; color: "#666" } GradientStop { position: 1.0; color: "#AAA" } } property alias text: instructionTxt.text Behavior on opacity { PropertyAnimation { duration: 200 } } //shows/hides the Instruction MouseArea { anchors.fill: parent onClicked: instruction.hide() enabled: instruction.opacity !== 0 } function show() { if(text) opacity = 0.8 } function hide() { opacity = 0 } } //display level objective GCText { id: instructionTxt anchors { top: background.vert ? parent.top : leftWidget.bottom topMargin: -10 horizontalCenter: background.horizontalCenter } opacity: instruction.opacity z: instruction.z fontSize: background.vert ? regularSize : smallSize color: "white" style: Text.Outline styleColor: "black" horizontalAlignment: Text.AlignHCenter width: Math.max(Math.min(parent.width * 0.8, text.length * 8), parent.width * 0.3) wrapMode: TextEdit.WordWrap } //display level objective GCText { id: warningTxt anchors { horizontalCenter: background.horizontalCenter verticalCenter: background.verticalCenter } opacity: warningRectangle.opacity z: warningRectangle.z + 1 fontSize: regularSize color: "white" style: Text.Outline styleColor: "black" horizontalAlignment: Text.AlignHCenter width: Math.max(Math.min(parent.width * 0.8, text.length * 8), parent.width * 0.3) wrapMode: TextEdit.WordWrap } Rectangle { id: warningRectangle anchors.fill: warningTxt opacity: 0 radius: 10 border.width: 2 z: 10 border.color: "black" gradient: Gradient { GradientStop { position: 0.0; color: "#000" } GradientStop { position: 0.9; color: "#666" } GradientStop { position: 1.0; color: "#AAA" } } property alias text: warningTxt.text Behavior on opacity { PropertyAnimation { duration: 200 } } //shows/hides the Instruction MouseArea { anchors.fill: parent onClicked: warningRectangle.hide() enabled: warningRectangle.opacity !== 0 } function show() { if(text) opacity = 0.8 } function hide() { opacity = 0 } } //dragable weights list (leftwidget) Rectangle { id: leftWidget width: background.vert ? items.cellSize * 1.74 : background.width height: background.vert ? background.height : items.cellSize * 1.74 color: "#FFFF42" border.color: "#FFD85F" border.width: 4 z: 4 //grid with ok button and the different draggable number weights Flickable { id: flickableElement anchors.fill: parent width: background.height height: leftWidget.width //contentHeight: gridView.height contentHeight: gridView.height * 1.8 //? contentWidth: leftWidget.width boundsBehavior: Flickable.DragAndOvershootBounds Grid { id: gridView x: 10 y: 10 width: parent.width height: background.height //width: background.vert ? leftWidget.width : 3 * bar.height // height: background.vert ? background.height - 2 * bar.height : bar.height spacing: 10 columns: background.vert ? 1 : 5 //ok button Image { id: okButton source:"qrc:/gcompris/src/core/resource/bar_ok.svg" sourceSize.width: items.cellSize * 1.5 fillMode: Image.PreserveAspectFit MouseArea { id: mouseArea anchors.fill: parent enabled: background.finished ? false : true onPressed: okButton.opacity = 0.6 onReleased: okButton.opacity = 1 onClicked: { Activity.checkAnswer() } } } // numbers classes drag elements Repeater { id: numberClassDragElements model: numberClassDragListModel NumberClassDragElement { id: classDragElement name: model.name color: model.color Drag.keys: model.dragkeys } } // numbers columns weights and numbers weigths drag elements Repeater { id: numberWeightDragElements model: numberWeightDragListModel NumberWeightDragElement { id: weightComponentDragElement name: model.name imageName: model.imageName Drag.keys: model.dragkeys weightValue: model.weightValue caption: model.caption color: model.color selected: model.selected } } } } } //bar buttons DialogHelp { id: dialogHelp onClose: home() } Bar { id: bar content: BarEnumContent { value: help | home | level | reload | config} onHelpClicked: { displayDialog(dialogHelp) } onPreviousLevelClicked: Activity.previousLevel() onNextLevelClicked: Activity.nextLevel() onHomeClicked: activity.home() onReloadClicked: Activity.reloadRandom() //? onConfigClicked: { dialogActivityConfig.active = true displayDialog(dialogActivityConfig) } } Bonus { id: bonus } } } diff --git a/src/activities/numeration_weights_integer/numeration_weights_integer.js b/src/activities/numeration_weights_integer/numeration_weights_integer.js index 3d192c8ec..8a9c24d18 100644 --- a/src/activities/numeration_weights_integer/numeration_weights_integer.js +++ b/src/activities/numeration_weights_integer/numeration_weights_integer.js @@ -1,600 +1,600 @@ /* GCompris - numeration.js * * Copyright (C) 2019 Emmanuel Charruau * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ .pragma library .import QtQuick 2.6 as Quick var currentLevel = 0 var numberOfLevel = 0 //? var items var numbersToConvert = [] var originalNumbersToConvert = [] var numbersCorrectlyAnswered = [] var scorePercentage = 0 var scorePourcentageStep = 0 var wrongAnswerAlreadyGiven = false var selectedNumberWeightDragElementIndex = -1 var numberHasADecimalPart = false var fullClassNamesConstantArray = ["Decimal Part","Unit class","Thousand class","Million class","Milliard class"] var classNamesUsedArray var numberClassesObj = { "Decimal Part": { name: qsTr("Decimal Part"), color: "black", dragkeys: "NumberClassKey"}, "Unit class": { name: qsTr("Unit class"), color: "black", dragkeys: "NumberClassKey"}, "Thousand class": { name: qsTr("Thousand class"), color: "black", dragkeys: "NumberClassKey"}, "Million class": { name: qsTr("Million class"), color: "black", dragkeys: "NumberClassKey"}, "Milliard class": { name: qsTr("Milliard class"), color: "black", dragkeys: "NumberClassKey"} } var numberWeightsColumnsArray = ["HundredColumn","TenColumn","UnitColumn"] var numberWeightComponentConstantArray = ["UnitColumn","TenColumn","HundredColumn","Unit","Ten","Hundred","Thousand","TenThousand", "OneHundredThousand","OneMillion","TenMillion","OneHundredMillion", "OneMilliard","TenMilliard","OneHundredMilliard"] var numberWeightDragArray = { "UnitColumn": { name: qsTr("Unit"), caption: "Unit", imageName: "", weightValue: "1", dragkeys: "numberWeightHeaderKey", color: "lightskyblue", selected: false }, "TenColumn": { name: qsTr("Ten"), caption: "Ten", imageName: "", weightValue: "10", dragkeys: "numberWeightHeaderKey", color: "lightskyblue", selected: false }, "HundredColumn": { name: qsTr("Hundred"), caption: "Hundred", imageName: "", weightValue: "100", dragkeys: "numberWeightHeaderKey", color: "lightskyblue", selected: false }, "Unit": { name: qsTr("Unit"), caption: "", imageName: "unit.svg", weightValue: "1", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "Ten": { name: qsTr("Unit"), caption: "", imageName: "ten.svg", weightValue: "10", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "Hundred": { name: qsTr("Unit"), caption: "", imageName: "hundred.svg", weightValue: "100", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "Thousand": { name: qsTr("Unit"), caption: "1000", imageName: "weightCaption.svg", weightValue: "1000", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "TenThousand": { name: qsTr("Unit"), caption: "10 000", imageName: "weightCaption.svg", weightValue: "10000", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "OneHundredThousand": { name: qsTr("Unit"), caption: "100 000", imageName: "weightCaption.svg", weightValue: "100000", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "OneMillion": { name: qsTr("Unit"), caption: "1 000 000", imageName: "weightCaption.svg", weightValue: "1000000", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "TenMillion": { name: qsTr("Unit"), caption: "10 000 000", imageName: "weightCaption.svg", weightValue: "10000000", dragkeys: "numberWeightKey", color: "transparent", selected: false }, "OneHundredMillion": { name: qsTr("Unit"), caption: "100 000 000", imageName: "weightCaption.svg", weightValue: "100000000", dragkeys: "numberWeightKey", color: "transparent" , selected: false }, "OneMilliard": { name: qsTr("Unit"), caption: "1 000 000 000", imageName: "weightCaption.svg", weightValue: "1000000000", dragkeys: "numberWeightKey", color: "transparent" , selected: false }, "TenMilliard": { name: qsTr("Unit"), caption: "10 000 000 000", imageName: "weightCaption.svg", weightValue: "10000000000", dragkeys: "numberWeightKey", color: "transparent" , selected: false }, "OneHundredMilliard": { name: qsTr("Unit"), caption: "100 000 000 000", imageName: "weightCaption.svg", weightValue: "100000000000", dragkeys: "numberWeightKey", color: "transparent" , selected: false } } // for what is used name in numberWeightDragArray ? //? var numberClassTypeColumnsArray = ["Integer Part","Decimal Part"] var tutorialInstructions = [ { - "instruction": qsTr("This activity teaches how to convert decimal numbers to binary numbers."), - "instructionQml" : "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial1.qml" + "instruction": qsTr("This activity teaches how to place numbers weights to represent a number quantity.") + //"instructionQml" : "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial1.qml" }, { - "instruction": qsTr("Computers use transistors to count and transistors have only two states, 0 and 1. Mathematically, these states are represented by 0 and 1, which makes up the binary system of numeration."), - "instructionQml" : "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial2.qml" + "instruction": qsTr("Before to enter any number weights you have to enter the number classes (unit class only if numbers are less than 1000 and unit classes and thousand class if they are more than 999.") + //"instructionQml" : "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial2.qml" }, { - "instruction": qsTr("In the activity 0 and 1 are simulated by bulbs, switched on or off."), - "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial3.qml" + "instruction": qsTr("Here using drag and drop we add the unit class and the thousand class."), + "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial1.qml" }, { "instruction": qsTr("Binary system uses these numbers very efficiently, allowing to count from 0 to 255 with 8 bits only."), "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial4.qml" }, { "instruction": qsTr("Each bit adds a progressive value, corresponding to the powers of 2, ascending from right to left: bit 1 → 2⁰=1 , bit 2 → 2¹=2 , bit 3 → 2²=4 , bit 4 → 2³=8 , bit 5 → 2⁴=16 , bit 6 → 2⁵=32 , bit 7 → 2⁶=64 , bit 8 → 2⁷=128."), "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial5.qml" }, { "instruction": qsTr("To convert a decimal 5 to a binary value, 1 and 4 are added."), "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial6.qml" }, { "instruction": qsTr("Their corresponding bits are set to 1, the others set to 0. Decimal 5 is equal to binary 101."), "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial7.qml" }, { "instruction": qsTr("This image will help you to compute bits' value."), "instructionQml": "qrc:/gcompris/src/activities/numeration_weights_integer/resource/tutorial5.qml" } ] function removeClassInNumberClassesArray(className) { console.log(numberClassesArray) var index = numberClassesArray.indexOf(className); if (index > -1) { numberClassesArray.splice(index, 1); } console.log(numberClassesArray) } function removeClassInNumberClassesArray() { numberClassesArray.pop(numberClass) } function setNumberWeightHeader(numberWeightImageTile,imageName,caption,weightValue) { if ( imageName !== "") { numberWeightImageTile.source = "qrc:/gcompris/src/activities/numeration_weights_integer/resource/images/" + imageName } numberWeightImageTile.caption = caption numberWeightImageTile.weightValue = weightValue } function setNumberWeightComponent(numberWeightImageTile,imageName,caption,weightValue) { if ( imageName !== "") { numberWeightImageTile.source = "qrc:/gcompris/src/activities/numeration_weights_integer/resource/images/" + imageName numberWeightImageTile.caption = caption numberWeightImageTile.weightValue = weightValue } } function removeNumberWeightComponent(numberWeightImageTile) { numberWeightImageTile.source = "" numberWeightImageTile.caption = "" numberWeightImageTile.weightValue = "" numberWeightImageTile.border.color = "black" } function resetNumerationTable() { for (var i = 0; i=0; i--,classNamesUsedIndex++) { if (items.numberClassListModel.get(i).name === classNamesUsedArray[classNamesUsedIndex]) { items.numberClassListModel.setProperty(i, "misplaced", false) } else { items.numberClassListModel.setProperty(i, "misplaced", true) allClassesColumnsInRightPositions = false } } return allClassesColumnsInRightPositions } function expectedAndEnteredValuesAreEquals() { var enteredValue = readNumerationTableEnteredValue() console.log("enteredValue/expected value:",enteredValue + " / " + parseInt(numbersToConvert[0],10)) //test if entered value is equal to number expected if (enteredValue === parseInt(numbersToConvert[0],10)) { return true } else { return false } } function checkEnteredValue() { var _expectedAndEnteredValuesAreEquals = expectedAndEnteredValuesAreEquals() if (_expectedAndEnteredValuesAreEquals) { return true } else { return false } } function evaluateAndDisplayProgresses(correctAnswer) { if (correctAnswer) { wrongAnswerAlreadyGiven = false items.bonus.good("flower") console.log("correct: scorePercentage before incrementation",scorePercentage) numbersCorrectlyAnswered.push(numbersToConvert.shift()) //remove first element and copy it in numbersCorrectlyAnswered scorePercentage = scorePercentage + scorePourcentageStep console.log("correct: scorePercentage after incrementation",scorePercentage) items.progressBar.value = scorePercentage if (scorePercentage > 97) { return true } items.numberToConvertRectangle.text = numbersToConvert[0] console.log("original NumbersToConvert: " + originalNumbersToConvert) console.log("NumbersToConvert: " + numbersToConvert) console.log("numbersCorrectlyAnswered: " + numbersCorrectlyAnswered) return } else { items.bonus.bad("flower") items.numberToConvertRectangle.text = numbersToConvert[0] console.log("incorrect: scorePercentage before incrementation",scorePercentage) console.log("wrongAnswerAlreadyGiven: ", wrongAnswerAlreadyGiven) if (wrongAnswerAlreadyGiven === false) { scorePercentage = scorePercentage - scorePourcentageStep if (scorePercentage < 0) scorePercentage = 0 items.progressBar.value = scorePercentage if (numbersToConvert.length < 2) { numbersToConvert.splice(2, 0, numbersCorrectlyAnswered[Math.floor(Math.random() * numbersCorrectlyAnswered.length)]) } console.log("number to convert before splice: ",numbersToConvert) numbersToConvert.splice(2, 0, numbersToConvert[0]); console.log("number to convert after splice: ",numbersToConvert) wrongAnswerAlreadyGiven = true console.log("incorrect: scorePercentage after incrementation",scorePercentage) } console.log("NumbersToConvert length: " + numbersToConvert.length) console.log("original NumbersToConvert: " + originalNumbersToConvert) console.log("NumbersToConvert: " + numbersToConvert) console.log("numbersCorrectlyAnswered: " + numbersCorrectlyAnswered) return false } } function start(items_) { items = items_ currentLevel = 0 setNumberWeightDragListModel(numberWeightComponentConstantArray) initLevel() numberOfLevel = items.levels.length // ? } function setNumberClassTypeListModel() { items.numberClassTypeModel.append({"numberClassType": "Integer Part", "numberClassTypeHeaderWidth": 0}) if (hasNumberADecimalPart()) { addDecimalHeaderToNumberClassTypeModel() } } function setClassNamesUsedArray(fullClassNamesArray) { var smallerNumberClass = items.levels[currentLevel].smallerNumberClass var biggerNumberClass = items.levels[currentLevel].biggerNumberClass if (!isClassNamePresentInfullClassNamesArray(fullClassNamesArray, smallerNumberClass)) { return fullClassNamesConstantArray } if (!isClassNamePresentInfullClassNamesArray(fullClassNamesArray, biggerNumberClass)) { return fullClassNamesConstantArray } return fullClassNamesArray.slice(fullClassNamesArray.indexOf(smallerNumberClass),fullClassNamesArray.indexOf(biggerNumberClass)+1) } function isClassNamePresentInfullClassNamesArray(fullClassNamesArray, className) { if (fullClassNamesArray.indexOf(className) !== -1) { return true } else { items.warningRectangle.text = qsTr("The class name \"" + className + "\" is not present in the available list: \"" + fullClassNamesArray+ "\". Check your configuration file (lower case or uppercase error?).") items.warningRectangle.show() return false } } function hasNumberADecimalPart() { for (var i=0; i * * Authors: * Timothée Giet * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.13 import GCompris 1.0 import "../../../core" import "../../../activities" Rectangle { id: tutorial1 + property bool animationIsRunning: animationIsRunning + Component.onCompleted: { console.log("tutorial1_screen_loaded") + myAnim.running = true + myAnimY.running = true } anchors.fill: parent color: "#80FFFFFF" - PropertyAnimation on x { - id: animationId - property bool animationIsRunning: false + Rectangle { + id: myRect + width: 100; height: 100 + color: "red" + z: 1000 + y: -200 - target: numberClassDragElements.itemAt(0); - to: 300; - duration: 500; - easing.type: Easing.OutBounce + NumberAnimation{ + id: myAnim - onStarted: { + target: numberClassDragElements.itemAt(0) + property: "x"; + to: background.width - background.width/5 + duration: 3000 + onStarted: { + animationIsRunning = true + numberClassDragElements.itemAt(0).animationIsRunning = animationIsRunning + console.log("onStarted") + } + onFinished: { + numberClassDragElements.itemAt(0).Drag.drop() + console.log("Sent Drag drop") + animationIsRunning = false + } + } - animationIsRunning = true - numberClassDragElements.itemAt(0).animationIsRunning = animationIsRunning - numberClassDragElements.itemAt(0).Drag.startDrag() + NumberAnimation{ + id: myAnimY + target: numberClassDragElements.itemAt(0) + property: "y"; + to: background.height / 5 + duration: 3000 } - onFinished: { - numberClassDragElements.itemAt(0).Drag.drop() - console.log("Sent Drag drop") - animationIsRunning = false - } } - PropertyAnimation on y { to: 400; duration: 500; easing.type: Easing.OutBounce } } diff --git a/src/activities/numeration_weights_integer/resource/tutorial2.qml b/src/activities/numeration_weights_integer/resource/tutorial2.qml index 5bd8f55af..c846e841a 100644 --- a/src/activities/numeration_weights_integer/resource/tutorial2.qml +++ b/src/activities/numeration_weights_integer/resource/tutorial2.qml @@ -1,67 +1,93 @@ /* GCompris - tutorial1.qml * * Copyright (C) 2018 Timothée Giet * * Authors: * Timothée Giet * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ -import QtQuick 2.6 +import QtQuick 2.13 import GCompris 1.0 import "../../../core" import "../../../activities" Rectangle { id: tutorial2 Component.onCompleted: { tutorial2.state = '' tutorial2.state === '' ? tutorial2.state = 'other' : tutorial2.state = '' console.log("test") + animid.running = true + + } anchors.fill: parent color: "#80FFFFFF" states: [ // This adds a second state to the container where the rectangle is farther to the right State { name: "other" PropertyChanges { target: numberClassDragElements.itemAt(0) - x: 300 - y: 300 + x: 500 + y: 500 + } } ] transitions: [ // This adds a transition that defaults to applying to all state changes Transition { // This applies a default NumberAnimation to any changes a state change makes to x or y properties - NumberAnimation { properties: "x,y" + NumberAnimation { + id: animid + + + + properties: "x,y" onRunningChanged: { - console.log("mince") + console.log("onRunningChanged") } + + + onStarted: { + + /* animationIsRunning = true + numberClassDragElements.itemAt(0).Drag.active = true //? had to add this line why? + numberClassDragElements.itemAt(0).animationIsRunning = animationIsRunning //? why is that not enough to set Drag.active? + numberClassDragElements.itemAt(0).Drag.startDrag()*/ + console.log("onStarted") + + } + + onFinished: { + // numberClassDragElements.itemAt(0).Drag.drop() + console.log("Sent Drag drop") + // animationIsRunning = false + } } } ] } diff --git a/src/core/Tutorial.qml b/src/core/Tutorial.qml index 4301d1a99..02688912e 100644 --- a/src/core/Tutorial.qml +++ b/src/core/Tutorial.qml @@ -1,216 +1,216 @@ /* GCompris - Tutorial.qml * * Copyright (C) 2017 Divyam Madaan * * Authors: * Divyam Madaan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ /* * A QML component for tutorial in activity in GCompris. * * Use Tutorial when you want to add a tutorial section which contains instructions and images. * * Contains the following basic layout elements: text (instructions), a Skip, * a Next and a Previous button to leave the tutorial or navigate through it. * The skipPressed, nextPressed, previousPressed signals are emitted when user clicks on skip, next and previous button respectively. * */ /* To use the component add: * Tutorial { * id: tutorialSection * source: "sourceForTutorialBackgroundImage" * tutorialDetails: Activity.tutorialInstructions * onSkipPressed: { * Activity.initLevel() * } * } */ import QtQuick 2.6 import GCompris 1.0 Item { id: tutorialSection anchors.fill: parent /* type: int * Counter for tutorial instructions */ property int tutorialNumber: 0 /* Container for all the tutorial instructions */ property var tutorialDetails - /* Do we use image or qml files for illustrations */ + /* Do we use image, qml files for illustrations, or do we not use any of them */ property bool useImage: true // Emitted when skipButton is clicked signal skipPressed // Emitted when nextButton is clicked signal nextPressed // Emitted when previousButton is clicked signal previousPressed property alias tutorialText: tutorialText // Tutorial instructions GCText { id: tutorialText anchors { horizontalCenter: parent.horizontalCenter top: parent.top topMargin: 10 } text: tutorialDetails ? tutorialDetails[tutorialNumber].instruction : "" fontSizeMode: Text.Fit minimumPixelSize: 10 color: "black" horizontalAlignment: Text.AlignHLeft width: Math.min(implicitWidth, 0.8 * parent.width) height: Math.min(implicitHeight, 0.25 * parent.height) wrapMode: Text.WordWrap z: 2 } MouseArea { anchors.fill: parent } Rectangle { id: tutorialTextContainer anchors.top: tutorialText.top anchors.horizontalCenter: tutorialText.horizontalCenter width: tutorialText.width + 20 height: tutorialText.height + 2 opacity: 0.8 radius: 10 border.width: 6 color: "white" border.color: "#87A6DD" } // previousButton: It emits skipPressed and navigates to previous tutorial when clicked IntroButton { id: previousButton width: parent.width / 5 height: 90 z: 5 anchors.right: nextButton.left anchors.topMargin: 15 anchors.rightMargin: 15 anchors.top: tutorialTextContainer.bottom visible: tutorialNumber != 0 text: qsTr("Previous") onClicked: { --tutorialNumber previousPressed() } } // nextButton: It emits nextPressed which navigates to next tutorial when clicked IntroButton { id: nextButton width: parent.width / 5 height: 90 z: 5 anchors.right: skipButton.left anchors.topMargin: 15 anchors.rightMargin: 15 anchors.top: tutorialTextContainer.bottom visible: tutorialNumber != (tutorialDetails.length - 1) text: qsTr("Next") onClicked: { ++tutorialNumber nextPressed() } } // skipButton: It emits the skipPressed signal which calls the initLevel to close the tutorial when clicked. IntroButton { id: skipButton width: parent.width / 5 height: 90 z: 5 anchors.right: parent.right anchors.rightMargin: 15 anchors.topMargin: 15 anchors.top: tutorialTextContainer.bottom text: nextButton.visible ? qsTr("Skip") : qsTr("Start") onClicked: { tutorialSection.visible = false skipPressed() } } IntroButton { id: showButton width: parent.width / 5 height: 90 z: 5 anchors.right: previousButton.visible ? previousButton.left : nextButton.left anchors.topMargin: 15 anchors.rightMargin: 15 anchors.top: tutorialTextContainer.bottom visible: tutorialNumber != (tutorialDetails.length - 1) text: qsTr("Show") onClicked: { ++tutorialNumber nextPressed() } } // Image component for tutorial instructions Image { id: tutorialImage visible: useImage width: parent.width * 0.8 height: (parent.height - nextButton.height) * 0.48 fillMode: Image.PreserveAspectFit source: tutorialDetails && useImage ? tutorialDetails[tutorialNumber].instructionImage : "" anchors { top: previousButton.bottom topMargin: 10 horizontalCenter: parent.horizontalCenter } } // Alternative QML component for tutorial instructions Loader { id: tutorialQml enabled: !tutorialImage.visible width: parent.width * 0.8 height: (parent.height - nextButton.height) * 0.48 - source: tutorialDetails && !useImage ? tutorialDetails[tutorialNumber].instructionQml : "" + source: tutorialDetails[tutorialNumber].instructionQml !== undefined && !useImage ? tutorialDetails[tutorialNumber].instructionQml : "" anchors { top: previousButton.bottom topMargin: 10 horizontalCenter: parent.horizontalCenter } } }