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

0001 /* GCompris - DigitalElectricity.qml
0002  *
0003  * SPDX-FileCopyrightText: 2016 Pulkit Gupta <pulkitnsit@gmail.com>
0004  *
0005  * Authors:
0006  *   Bruno Coudoin <bruno.coudoin@gcompris.net> (GTK+ version)
0007  *   Pulkit Gupta <pulkitnsit@gmail.com> (Qt Quick port)
0008  *   Rudra Nil Basu <rudra.nil.basu.1996@gmail.com> (Qt Quick port)
0009  *   Timothée Giet <animtim@gmail.com> (mouse drag refactoring)
0010  *
0011  *   SPDX-License-Identifier: GPL-3.0-or-later
0012  */
0013 import QtQuick 2.12
0014 import GCompris 1.0
0015 
0016 import "../../core"
0017 import "digital_electricity.js" as Activity
0018 
0019 ActivityBase {
0020     id: activity
0021 
0022     onStart: focus = true
0023     onStop: {}
0024 
0025     pageComponent: Image {
0026         id: background
0027         anchors.fill: parent
0028         source: Activity.url + "texture02.webp"
0029         fillMode: Image.Tile
0030         signal start
0031         signal stop
0032 
0033         property bool hori: background.width >= background.height
0034 
0035         Component.onCompleted: {
0036             dialogActivityConfig.initialize()
0037             activity.start.connect(start)
0038             activity.stop.connect(stop)
0039         }
0040 
0041         // Needed to get keyboard focus on IntroMessage
0042         Keys.forwardTo: tutorialInstruction
0043 
0044         Keys.onPressed: {
0045             if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && okButton.enabled) {
0046                 Activity.checkAnswer()
0047             }
0048             if (event.key === Qt.Key_Plus) {
0049                 Activity.zoomIn()
0050             }
0051             if (event.key === Qt.Key_Minus) {
0052                 Activity.zoomOut()
0053             }
0054             if (event.key === Qt.Key_Right) {
0055                 playArea.x -= 200;
0056             }
0057             if (event.key === Qt.Key_Left) {
0058                 playArea.x += 200
0059             }
0060             if (event.key === Qt.Key_Up) {
0061                 playArea.y += 200
0062             }
0063             if (event.key === Qt.Key_Down) {
0064                 playArea.y -= 200
0065             }
0066             if (playArea.x >= mousePan.drag.maximumX) {
0067                 playArea.x = mousePan.drag.maximumX
0068             }
0069             if (playArea.y >= mousePan.drag.maximumY) {
0070                 playArea.y = mousePan.drag.maximumY
0071             }
0072             if (playArea.x <= mousePan.drag.minimumX) {
0073                 playArea.x = mousePan.drag.minimumX
0074             }
0075             if (playArea.y <= mousePan.drag.minimumY) {
0076                 playArea.y = mousePan.drag.minimumY
0077             }
0078         }
0079 
0080         onHoriChanged: {
0081             if (hori == true) {
0082                 playArea.x += items.toolsMargin
0083                 playArea.y -= items.toolsMargin
0084             } else {
0085                 playArea.x -= items.toolsMargin
0086                 playArea.y += items.toolsMargin
0087             }
0088         }
0089 
0090         // Add here the QML items you need to access in javascript
0091         QtObject {
0092             id: items
0093             property Item main: activity.main
0094             property alias playArea: playArea
0095             property alias mousePan: mousePan
0096             property int currentLevel: activity.currentLevel
0097             property alias bonus: bonus
0098             property alias availablePieces: availablePieces
0099             property alias toolTip: toolTip
0100             property alias infoTxt: infoTxt
0101             property alias truthTablesModel: truthTablesModel
0102             property alias displayTruthTable: inputOutputTxt.displayTruthTable
0103             property alias dataset: dataset
0104             property alias tutorialDataset: tutorialDataset
0105             property string mode: "tutorial"
0106             property bool isTutorialMode: mode == "tutorial" ? true : false
0107             property alias infoImage: infoImage
0108             property alias tutorialInstruction: tutorialInstruction
0109             property real toolsMargin: 90 * ApplicationInfo.ratio
0110             property real zoomLvl: 0.25
0111         }
0112 
0113         Loader {
0114             id: dataset
0115             asynchronous: false
0116         }
0117 
0118         TutorialDataset {
0119             id: tutorialDataset
0120         }
0121 
0122         IntroMessage {
0123             id: tutorialInstruction
0124             intro: []
0125             textContainerWidth: background.hori ? parent.width - inputComponentsContainer.width - items.toolsMargin : 0.9 * background.width
0126             textContainerHeight: background.hori ? 0.5 * parent.height : parent.height - inputComponentsContainer.height - (bar.height * 2) - items.toolsMargin
0127             anchors {
0128                 fill: undefined
0129                 top: background.hori ? parent.top : inputComponentsContainer.bottom
0130                 topMargin: 10
0131                 right: parent.right
0132                 rightMargin: 5
0133                 left: background.hori ? inputComponentsContainer.right : parent.left
0134                 leftMargin: 5
0135             }
0136             z: 5
0137         }
0138 
0139         onStart: { Activity.start(items) }
0140         onStop: { Activity.stop() }
0141 
0142         Rectangle {
0143             id: visibleArea
0144             color: "#00000000"
0145             width: background.hori ? background.width - items.toolsMargin - 10 : background.width - 10
0146             height: background.hori ? background.height - bar.height - items.toolsMargin - 10 : background.height - bar.height - 10
0147             anchors {
0148                 fill: undefined
0149                 top: background.hori ? parent.top : inputComponentsContainer.bottom
0150                 topMargin: 5
0151                 right: parent.right
0152                 rightMargin: 5
0153                 left: background.hori ? inputComponentsContainer.right : parent.left
0154                 leftMargin: 5
0155                 bottom: bar.top
0156                 bottomMargin: 20
0157             }
0158             z: 6
0159 
0160             GCText {
0161                 id: infoTxt
0162                 anchors {
0163                     horizontalCenter: parent.horizontalCenter
0164                     top: parent.top
0165                     topMargin: 2
0166                 }
0167                 fontSizeMode: Text.Fit
0168                 minimumPixelSize: 10
0169                 font.pixelSize: 150
0170                 color: "white"
0171                 horizontalAlignment: Text.AlignHLeft
0172                 width: Math.min(implicitWidth, 0.90 * parent.width)
0173                 height:  inputOutputTxt.visible == false ? Math.min(implicitHeight, 0.7 * parent.height) :
0174                         Math.min(implicitHeight, (inputOutputTxt.inputs > 2 ? 0.3 : 0.4) * parent.height)
0175                 wrapMode: TextEdit.WordWrap
0176                 visible: false
0177                 z: 4
0178             }
0179 
0180             Rectangle {
0181                 id: infoTxtContainer
0182                 anchors.fill: parent
0183                 opacity: 1
0184                 radius: 10
0185                 color: "#373737"
0186                 border.width: 2
0187                 border.color: "#F2F2F2"
0188                 visible: infoTxt.visible
0189                 MouseArea {
0190                     anchors.fill: parent
0191                     onClicked: infoTxt.visible = false
0192                 }
0193                 z: 3
0194             }
0195 
0196             Image {
0197                 id: infoImage
0198                 property bool imgVisible: false
0199                 height: source == "" ? 0 : parent.height * 0.3 - 10
0200                 width: source == "" ? 0 : parent.width - 10
0201                 fillMode: Image.PreserveAspectFit
0202                 visible: infoTxt.visible && imgVisible
0203                 anchors {
0204                     top: infoTxt.bottom
0205                     horizontalCenter: infoTxtContainer.horizontalCenter
0206                 }
0207                 z: 5
0208             }
0209 
0210             ListModel {
0211                 id: truthTablesModel
0212                 property int rows
0213                 property int columns
0214                 property int inputs
0215                 property int outputs
0216             }
0217 
0218             Row {
0219                 id: inputOutputTxt
0220                 z: 5
0221                 property bool displayTruthTable
0222                 visible: infoTxt.visible && displayTruthTable
0223                 property int inputs: truthTablesModel.inputs
0224                 property int outputs: truthTablesModel.outputs
0225                 property int cellSize: (inputs > 2 ? 0.65 : 0.5) * parent.height / (truthTablesModel.rows + 1)
0226                 property int maxWidth: Math.min(cellSize, parent.width * 0.95 / truthTablesModel.columns)
0227                 property int minSize: 2.5 * cellSize
0228                 height: cellSize
0229                 anchors {
0230                     top: infoTxt.bottom
0231                     horizontalCenter: parent.horizontalCenter
0232                 }
0233                 Rectangle {
0234                     color: "#A7D9F9"
0235                     width: inputOutputTxt.inputs > 1 ? inputOutputTxt.maxWidth * inputOutputTxt.inputs : inputOutputTxt.minSize
0236                     height: inputOutputTxt.cellSize
0237                     border.color: "#373737"
0238                     border.width: 1
0239                     GCText {
0240                         anchors.centerIn: parent
0241                         fontSizeMode: Text.Fit
0242                         minimumPixelSize: 10
0243                         color: "#353535"
0244                         horizontalAlignment: Text.AlignHCenter
0245                         verticalAlignment: Text.AlignVCenter
0246                         height: parent.height
0247                         width: parent.width
0248                         text: qsTr("Input")
0249                     }
0250                 }
0251                 Rectangle {
0252                     color: "#A7F9DD"
0253                     width: inputOutputTxt.outputs > 1 ? inputOutputTxt.maxWidth * inputOutputTxt.outputs : inputOutputTxt.minSize
0254                     height: inputOutputTxt.cellSize
0255                     border.color: "#373737"
0256                     border.width: 1
0257                     GCText {
0258                         anchors.centerIn: parent
0259                         fontSizeMode: Text.Fit
0260                         minimumPixelSize: 10
0261                         color: "#353535"
0262                         horizontalAlignment: Text.AlignHCenter
0263                         verticalAlignment: Text.AlignVCenter
0264                         height: parent.height
0265                         width: parent.width
0266                         text: qsTr("Output")
0267                     }
0268                 }
0269             }
0270 
0271             Grid {
0272                 id: truthTable
0273                 rows: truthTablesModel.rows
0274                 columns: truthTablesModel.columns
0275                 height: rows * inputOutputTxt.cellSize
0276                 z: 5
0277                 visible: inputOutputTxt.visible
0278                 anchors {
0279                     top: inputOutputTxt.bottom
0280                     horizontalCenter: parent.horizontalCenter
0281                 }
0282                 Repeater {
0283                     id: repeater
0284                     model: truthTablesModel
0285                     delegate: blueSquare
0286                     Component {
0287                         id: blueSquare
0288                         Rectangle {
0289                             width: ((index % truthTable.columns) / (truthTablesModel.inputs - 1)) <= 1 ?
0290                                    (inputOutputTxt.inputs > 1 ? inputOutputTxt.maxWidth : inputOutputTxt.minSize) :
0291                                    (inputOutputTxt.outputs > 1 ? inputOutputTxt.maxWidth : inputOutputTxt.minSize)
0292                             height: inputOutputTxt.cellSize
0293                             border.color: "#373737"
0294                             border.width: 1
0295                             color: {
0296                                 if(truthTablesModel.inputs == 1) {
0297                                     return index%2 == 0 ? "#A7D9F9" : "#A7F9DD"
0298                                 }
0299                                 else {
0300                                     return ((index % truthTable.columns) / (truthTablesModel.inputs - 1)) <= 1 ? "#A7D9F9" : "#A7F9DD"
0301                                 }
0302                             }
0303 
0304                             GCText {
0305                                 id: truthTableValue
0306                                 anchors.centerIn: parent
0307                                 fontSizeMode: Text.Fit
0308                                 minimumPixelSize: 10
0309                                 color: "#353535"
0310                                 horizontalAlignment: Text.AlignHCenter
0311                                 height: parent.height
0312                                 width: parent.width
0313                                 text: value
0314                             }
0315                         }
0316                     }
0317                 }
0318             }
0319 
0320         }
0321 
0322         Rectangle {
0323             id: playArea
0324             color: "#10000000"
0325             x: background.hori ? items.toolsMargin : 0
0326             y: background.hori ? 0 : items.toolsMargin
0327             width: background.hori ?
0328                        background.width * 4 - items.toolsMargin : background.width * 4
0329             height: background.hori ?
0330                        background.height * 4 - (bar.height * 1.1) :
0331                        background.height * 4 - (bar.height * 1.1) - items.toolsMargin
0332 
0333             PinchArea {
0334                 id: pinchZoom
0335                 anchors.fill: parent
0336                 onPinchFinished: {
0337                     if (pinch.scale < 1) {
0338                         Activity.zoomOut()
0339                     }
0340                     if (pinch.scale > 1) {
0341                         Activity.zoomIn()
0342                     }
0343                 }
0344                 MouseArea {
0345                     id: mousePan
0346                     anchors.fill: parent
0347                     scrollGestureEnabled: false //needed for pinchZoom
0348                     drag.target: playArea
0349                     drag.axis: Drag.XandYAxis
0350                     drag.minimumX: - playArea.width * items.zoomLvl
0351                     drag.maximumX: background.hori ? items.toolsMargin : 0
0352                     drag.minimumY: - playArea.height * items.zoomLvl
0353                     drag.maximumY: background.hori ? 0 : items.toolsMargin
0354                     onClicked: {
0355                         Activity.disableToolDelete();
0356                         Activity.deselect();
0357                         availablePieces.hideToolbar();
0358                     }
0359                 }
0360             }
0361         }
0362 
0363         Rectangle {
0364             id: inputComponentsContainer
0365             width: background.hori ?
0366                        items.toolsMargin :
0367                        background.width
0368             height: background.hori ?
0369                         background.height :
0370                         items.toolsMargin
0371             color: "#4A3823"
0372             anchors.left: parent.left
0373             Image {
0374                 anchors.fill: parent
0375                 anchors.rightMargin: background.hori ? 3 * ApplicationInfo.ratio : 0
0376                 anchors.bottomMargin: background.hori ? 0 : 3 * ApplicationInfo.ratio
0377                 source: Activity.url + "texture01.webp"
0378                 fillMode: Image.Tile
0379                 ListWidget {
0380                     id: availablePieces
0381                     hori: background.hori
0382                 }
0383             }
0384             z: 10
0385         }
0386 
0387         Rectangle {
0388             id: toolTip
0389             anchors {
0390                 bottom: bar.top
0391                 bottomMargin: 10
0392                 left: inputComponentsContainer.left
0393                 leftMargin: 5
0394             }
0395             width: toolTipTxt.width + 10
0396             height: toolTipTxt.height + 5
0397             color: "#373737"
0398             opacity: 1
0399             radius: 10
0400             z: 100
0401             border.width: 2
0402             border.color: "#F2F2F2"
0403             property alias text: toolTipTxt.text
0404             Behavior on opacity { NumberAnimation { duration: 120 } }
0405 
0406             function show(newText) {
0407                 if(newText) {
0408                     text = newText
0409                     opacity = 1
0410                 } else {
0411                     opacity = 0
0412                 }
0413             }
0414 
0415             GCText {
0416                 id: toolTipTxt
0417                 anchors.centerIn: parent
0418                 fontSize: regularSize
0419                 color: "white"
0420                 horizontalAlignment: Text.AlignHCenter
0421                 wrapMode: TextEdit.WordWrap
0422             }
0423         }
0424 
0425         DialogChooseLevel {
0426             id: dialogActivityConfig
0427             currentActivity: activity.activityInfo
0428             onClose: {
0429                 home();
0430             }
0431             onLoadData: {
0432                 if(activityData && activityData["mode"]) {
0433                     items.mode = activityData["mode"];
0434                 }
0435             }
0436         }
0437 
0438         DialogHelp {
0439             id: dialogHelp
0440             onClose: home()
0441         }
0442 
0443         BarButton {
0444             id: okButton
0445             visible: items.isTutorialMode
0446             anchors {
0447                 bottom: bar.top
0448                 right: parent.right
0449                 rightMargin: 10 * ApplicationInfo.ratio
0450                 bottomMargin: height * 0.5
0451             }
0452             source: "qrc:/gcompris/src/core/resource/bar_ok.svg"
0453             sourceSize.width: 60 * ApplicationInfo.ratio
0454             enabled: !tutorialInstruction.visible && !bonus.isPlaying
0455             onClicked: Activity.checkAnswer()
0456         }
0457 
0458         Bar {
0459             id: bar
0460             level: items.currentLevel + 1
0461             content: BarEnumContent { value: help | home | (items.isTutorialMode ? level : 0) | reload | activityConfig}
0462             onHelpClicked: {displayDialog(dialogHelp)}
0463             onPreviousLevelClicked: Activity.previousLevel()
0464             onNextLevelClicked: Activity.nextLevel()
0465             onHomeClicked: home()
0466             onReloadClicked: Activity.reset()
0467             onActivityConfigClicked: {
0468                 displayDialog(dialogActivityConfig)
0469             }
0470         }
0471 
0472         Bonus {
0473             id: bonus
0474             Component.onCompleted: win.connect(Activity.nextLevel)
0475         }
0476     }
0477 
0478 }