Warning, /education/gcompris/src/activities/superbrain/Superbrain.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - Superbrain.qml 0002 * 0003 * SPDX-FileCopyrightText: 2015 Holger Kaelberer <holger.k@elberer.de> 0004 * 0005 * Authors: 0006 * Bruno Coudoin <bruno.coudoin@gcompris.net> (GTK+ version) 0007 * Holger Kaelberer <holger.k@elberer.de> (Qt Quick port) 0008 * 0009 * SPDX-License-Identifier: GPL-3.0-or-later 0010 */ 0011 import QtQuick 2.12 0012 0013 import "../../core" 0014 import "superbrain.js" as Activity 0015 import GCompris 1.0 0016 0017 ActivityBase { 0018 id: activity 0019 0020 onStart: focus = true 0021 onStop: {} 0022 0023 pageComponent: Image { 0024 id: background 0025 source: "qrc:/gcompris/src/activities/family/resource/background.svg" 0026 sourceSize.width: width 0027 sourceSize.height: height 0028 fillMode: Image.PreserveAspectCrop 0029 focus: true 0030 0031 readonly property double scaleFactor: 1 0032 readonly property bool isPortrait: (height >= width) 0033 0034 signal start 0035 signal stop 0036 0037 MouseArea { 0038 anchors.fill: parent 0039 onClicked: showChooser(false); 0040 } 0041 0042 Component.onCompleted: { 0043 dialogActivityConfig.initialize() 0044 activity.start.connect(start) 0045 activity.stop.connect(stop) 0046 } 0047 0048 QtObject { 0049 id: items 0050 property Item main: activity.main 0051 property alias background: background 0052 property int currentLevel: activity.currentLevel 0053 property alias bonus: bonus 0054 property alias score: score 0055 property alias colorsRepeater: colorsRepeater 0056 property alias chooserGrid: chooserGrid 0057 property alias guessModel: guessModel 0058 property alias guessColumn: guessColumn 0059 property alias currentRepeater: currentRepeater 0060 property string mode: "color" 0061 property GCSfx audioEffects: activity.audioEffects 0062 property bool buttonsBlocked: false 0063 } 0064 0065 onStart: { Activity.start(items) } 0066 onStop: { 0067 chooserTimer.stop() 0068 Activity.stop() 0069 } 0070 0071 Column { 0072 id: colorsColumn 0073 0074 anchors.left: parent.left 0075 anchors.leftMargin: 5 * ApplicationInfo.ratio 0076 anchors.top: parent.top 0077 anchors.topMargin: 5 * ApplicationInfo.ratio 0078 0079 spacing: 3 * ApplicationInfo.ratio 0080 0081 width: guessColumn.guessSize 0082 height: guessColumn.guessSize 0083 0084 add: Transition { 0085 NumberAnimation { properties: "y"; duration: 1000; easing.type: Easing.OutBounce } 0086 } 0087 0088 Repeater { 0089 id: colorsRepeater 0090 0091 model: ListModel {} 0092 0093 delegate: SearchItem { 0094 width: 40 * ApplicationInfo.ratio 0095 height: 40 * ApplicationInfo.ratio 0096 border.width: 2 0097 border.color: "#373737" 0098 searchItemIndex: itemIndex 0099 } 0100 } 0101 } 0102 0103 Rectangle { 0104 id: tooltipRect 0105 width: 100 * ApplicationInfo.ratio 0106 height: tooltipText.height + 10 * ApplicationInfo.ratio 0107 radius: 4 0108 x: 0 0109 y: 0 0110 color: "lightgray" 0111 opacity: 0 0112 z: 10 0113 property alias text: tooltipText.text 0114 0115 GCText { 0116 id: tooltipText 0117 anchors.centerIn: parent 0118 fontSize: 13 0119 text: "" 0120 color: "black" 0121 0122 onTextChanged: parent.width = width + 10 0123 } 0124 0125 Behavior on opacity { 0126 NumberAnimation { duration: 100 } 0127 } 0128 } 0129 0130 function showTooltip(visible, status, mouseArea) 0131 { 0132 if (!visible || status === Activity.STATUS_UNKNOWN) { 0133 tooltipRect.opacity = 0; 0134 return; 0135 } 0136 showChooser(false); 0137 0138 var obj = background.mapFromItem(mouseArea, mouseArea.mouseX, mouseArea.mouseY); 0139 0140 if (status === Activity.STATUS_CORRECT) 0141 tooltipRect.text = qsTr("This item is well placed."); 0142 if (status === Activity.STATUS_MISPLACED) 0143 tooltipRect.text = qsTr("This item is misplaced."); 0144 tooltipRect.x = obj.x - 5 - tooltipRect.width; 0145 tooltipRect.y = obj.y - 5 - tooltipRect.height; 0146 tooltipRect.opacity = 0.9; 0147 } 0148 0149 function showChooser(visible, guessIndex, item) 0150 { 0151 if (!visible) { 0152 chooserTimer.stop(); 0153 chooser.scale = 0; 0154 return; 0155 } 0156 var modelObj = guessModel.get(0).guess.get(guessIndex); 0157 var absolute = currentRow.mapToItem(background, item.x, item.y); 0158 chooserGrid.colIndex = modelObj.colIndex; 0159 chooserGrid.guessIndex = guessIndex; 0160 var chooserOffset = 0.5*chooser.width - item.width/2; 0161 var arrowOffset = 0; 0162 var targetX = item.x - chooserOffset; 0163 // beyond left screen border: 0164 if (absolute.x - chooserOffset < 0) { 0165 arrowOffset = absolute.x - chooserOffset; 0166 targetX -= arrowOffset; 0167 } 0168 // beyond right screen border: 0169 if (absolute.x + chooserOffset + item.width > background.width) { 0170 arrowOffset = absolute.x + chooserOffset + item.width - background.width; 0171 targetX -= arrowOffset; 0172 } 0173 0174 chooser.x = targetX; 0175 chooser.arrowOffset = arrowOffset; 0176 var targetY = item.y - chooser.height - 15; 0177 var targetAbove = true; 0178 /* //only on top-level, at window border: 0179 if (targetY < 0) { 0180 targetY = item.y + guessColumn.guessSize + 10; 0181 targetAbove = false; 0182 }*/ 0183 chooser.y = targetY; 0184 chooser.above = targetAbove; 0185 chooser.scale = 1; 0186 chooser.visible = true; 0187 chooserTimer.restart(); 0188 //console.log("XXX chooser at item.x=" + item.x + " absolute.x=" + absolute.x + " chooser.x/w=" + chooser.x + "/" + chooser.width + " background.width=" + background.width + " currentRow.x/y/w/h=" + currentRow.x + "/" + currentRow.y + "/" + currentRow.width + "/" + currentRow.height + " guessIdx=" + guessIndex + " arrowOff=" + arrowOffset); 0189 } 0190 0191 Item { 0192 id: currentWrapper 0193 0194 width: currentRow.width 0195 height: currentRow.height 0196 z: 8 0197 0198 anchors.horizontalCenter: parent.horizontalCenter 0199 anchors.bottomMargin: 20 * ApplicationInfo.ratio 0200 0201 state: ApplicationSettings.isBarHidden ? "hidden" : "shown" 0202 states: [ 0203 State { 0204 name: "hidden" 0205 when: ApplicationSettings.isBarHidden 0206 AnchorChanges { 0207 target: currentWrapper; 0208 anchors.bottom: parent.bottom 0209 } 0210 }, 0211 State { 0212 name: "shown" 0213 when: !ApplicationSettings.isBarHidden 0214 AnchorChanges { 0215 target: currentWrapper; 0216 anchors.bottom: bar.top 0217 } 0218 } 0219 ] 0220 0221 transitions: Transition { 0222 AnchorAnimation { duration: 800; easing.type: Easing.OutBounce } 0223 } 0224 0225 Rectangle { 0226 id: chooser 0227 0228 width: chooserGrid.width + 15 0229 height: chooserGrid.height + 15 0230 0231 color: "darkgray" 0232 border.width: 0 0233 border.color: "white" 0234 0235 opacity: 1 0236 scale: 0 0237 visible: false 0238 z: 10 0239 0240 property bool above: true 0241 property real arrowOffset: 0 0242 0243 Rectangle { 0244 id: chooserArrow 0245 width: 10 0246 height: 10 0247 0248 x: chooser.width / 2 - 5 + chooser.arrowOffset 0249 y: chooser.above ? (chooser.height - 5) : (-5) 0250 color: chooser.color 0251 z: chooser.z 0252 transform: Rotation { origin.x: 5; origin.y: 5; angle: 45} 0253 } 0254 0255 GridView { 0256 id: chooserGrid 0257 0258 cellWidth: guessColumn.guessSize * 2 0259 cellHeight: guessColumn.guessSize * 2 0260 width: Math.ceil(count / 2) * cellWidth 0261 height: 2 * cellHeight 0262 anchors.centerIn: parent 0263 z: 11 0264 0265 clip: false 0266 interactive: false 0267 verticalLayoutDirection: GridView.TopToBottom 0268 layoutDirection: Qt.LeftToRight 0269 flow: GridView.FlowLeftToRight 0270 0271 property int colIndex: 0 0272 property int guessIndex: 0 0273 0274 Timer { 0275 id: chooserTimer 0276 interval: 5000 0277 onTriggered: showChooser(false); 0278 } 0279 0280 model: new Array() 0281 0282 delegate: SearchItem { 0283 id: chooserItem 0284 width: chooserGrid.cellWidth 0285 height: chooserGrid.cellWidth 0286 border.width: index == chooserGrid.colIndex ? 3 : 1 0287 border.color: index == chooserGrid.colIndex ? "#373737" : "darkgray" 0288 highlightSymbol: index == chooserGrid.colIndex 0289 searchItemIndex: modelData 0290 radius: 5 0291 0292 MouseArea { 0293 id: chooserMouseArea 0294 anchors.fill: parent 0295 acceptedButtons: Qt.LeftButton 0296 enabled: chooser.scale !== 0 && !bonus.isPlaying 0297 z: 11 0298 hoverEnabled: ApplicationInfo.isMobile ? false : true 0299 0300 onClicked: { 0301 chooserGrid.colIndex = chooserItem.searchItemIndex; 0302 var obj = items.guessModel.get(0); 0303 obj.guess.setProperty(chooserGrid.guessIndex, "colIndex", chooserGrid.colIndex); 0304 showChooser(false); 0305 } 0306 } 0307 } 0308 } 0309 Behavior on scale { 0310 NumberAnimation { duration: 100 } 0311 } 0312 } 0313 0314 Row { 0315 id: currentRow 0316 visible: true 0317 0318 property double factor: 1.9 0319 0320 anchors.left: parent.left 0321 anchors.top: parent.top 0322 0323 spacing: guessColumn.horizSpacing * factor 0324 height: guessColumn.guessSize * factor 0325 scale: 1 0326 z: 9 0327 0328 Repeater { 0329 id: currentRepeater 0330 0331 delegate: SearchItem { 0332 id: currentGuess 0333 0334 width: guessColumn.guessSize * currentRow.factor 0335 height: guessColumn.guessSize * currentRow.factor 0336 border.width: 2 * currentRow.factor 0337 border.color: "#373737" 0338 searchItemIndex: colIndex 0339 opacity: 1.0 0340 z: 2 0341 0342 MouseArea { 0343 id: mouseArea 0344 anchors.fill: parent 0345 acceptedButtons: Qt.LeftButton | Qt.RightButton 0346 enabled: !bonus.isPlaying 0347 z: 3 0348 hoverEnabled: ApplicationInfo.isMobile ? false : true 0349 0350 onPressAndHold: { 0351 if (guessColumn.count > 1) 0352 guessModel.get(0).guess.get(index).colIndex = guessModel.get(1).guess.get(index).colIndex; 0353 } 0354 0355 onClicked: { 0356 var obj = items.guessModel.get(0).guess.get(index); 0357 if(chooserTimer.running && chooserGrid.guessIndex === index) { 0358 if (mouse.button == Qt.LeftButton) 0359 obj.colIndex = (obj.colIndex == 0360 Activity.currentIndeces.length - 1) ? 0 : obj.colIndex + 1; 0361 else 0362 obj.colIndex = (obj.colIndex == 0) ? 0363 Activity.currentIndeces.length - 1 : obj.colIndex - 1; 0364 } 0365 showChooser(true, index, parent); 0366 } 0367 } 0368 states: State { 0369 name: "scaled"; when: mouseArea.containsMouse 0370 PropertyChanges { 0371 target: currentGuess 0372 scale: 1.1 0373 } 0374 } 0375 transitions: Transition { 0376 NumberAnimation { properties: "scale"; easing.type: Easing.OutCubic } 0377 } 0378 } 0379 } 0380 0381 BarButton { 0382 id: okButton 0383 enabled: !items.buttonsBlocked 0384 source: "qrc:/gcompris/src/core/resource/bar_ok.svg" 0385 sourceSize.width: 66 * bar.barZoom 0386 width: guessColumn.guessSize * currentRow.factor 0387 height: guessColumn.guessSize * currentRow.factor 0388 visible: true 0389 z: 8 0390 onClicked: { 0391 showChooser(false); 0392 Activity.checkGuess(); 0393 } 0394 } 0395 } 0396 } 0397 0398 ListModel { 0399 id: guessModel 0400 dynamicRoles: true 0401 } 0402 0403 ListView { 0404 id: guessColumn 0405 0406 anchors.horizontalCenter: parent.horizontalCenter 0407 anchors.bottom: currentWrapper.top 0408 anchors.bottomMargin: 10 * ApplicationInfo.ratio 0409 0410 boundsBehavior: Flickable.DragOverBounds 0411 verticalLayoutDirection: ListView.BottomToTop 0412 0413 readonly property int guessSize: 30 * ApplicationInfo.ratio 0414 readonly property int vertSpacing: 15 * ApplicationInfo.ratio 0415 readonly property int horizSpacing: 15 * ApplicationInfo.ratio 0416 readonly property int statusMargin: 5 * ApplicationInfo.ratio 0417 readonly property int resultSize: 10 * ApplicationInfo.ratio 0418 readonly property int guessColWidth: Activity.maxPieces * (guessSize + (2 * guessColumn.statusMargin)) 0419 + (Activity.maxPieces-1) * horizSpacing; 0420 readonly property int resultColWidth: Activity.maxPieces * resultSize 0421 + (Activity.maxPieces-1) * 2; 0422 0423 spacing: vertSpacing 0424 0425 width: guessColWidth + 10 + (2 * horizSpacing) + resultColWidth 0426 height: count * (guessSize + vertSpacing) 0427 0428 displaced: Transition { 0429 NumberAnimation { easing.type: Easing.OutCubic; properties: "y"; duration: 300 } 0430 } 0431 0432 model: guessModel 0433 0434 delegate: Row { 0435 id: guessRow 0436 width: guessColumn.width 0437 height: guessColumn.guessSize 0438 spacing: guessColumn.horizSpacing 0439 property int rowIndex: index 0440 visible: index != 0 0441 0442 Item { 0443 id: guessRowSpacer 0444 width: guessColumn.guessColWidth - 0445 (guessRepeater.count * (guessColumn.guessSize + 0446 (2 * guessColumn.statusMargin) + guessColumn.horizSpacing)) 0447 height: parent.height 0448 } 0449 0450 Repeater { 0451 id: guessRepeater 0452 anchors.left: parent.left 0453 anchors.top: parent.top 0454 model: guess 0455 0456 delegate: Item { // wrapper needed for singleGuessStatusRect's opacity 0457 id: singleGuessWrapper 0458 0459 width: guessColumn.guessSize + (2 * guessColumn.statusMargin); 0460 height: guessColumn.guessSize + (2 * guessColumn.statusMargin); 0461 0462 Rectangle { 0463 id: singleGuessStatusRect 0464 border.width: 2 0465 border.color: (status == Activity.STATUS_CORRECT) ? "white" : "black"; 0466 anchors.fill: parent 0467 radius: 3 0468 color: (status == Activity.STATUS_CORRECT) ? "black" : "white"; 0469 opacity: (status == Activity.STATUS_UNKNOWN) ? 0 : 0.9 0470 z: 1 0471 0472 MouseArea { 0473 id: mouseAreaRect 0474 anchors.fill: parent 0475 acceptedButtons: Qt.LeftButton 0476 enabled: guessRow.rowIndex > 0 && !bonus.isPlaying 0477 z: 4 0478 hoverEnabled: ApplicationInfo.isMobile ? false : true 0479 0480 Timer { 0481 id: tooltipTimer 0482 repeat: false 0483 interval: 500 0484 signal stopTimer 0485 0486 Component.onCompleted: { 0487 activity.stop.connect(stopTimer); 0488 } 0489 0490 onStopTimer: { 0491 stop(); 0492 } 0493 0494 onTriggered: showTooltip(true, status, mouseAreaRect) 0495 } 0496 0497 onEntered: tooltipTimer.restart() 0498 0499 onExited: { 0500 tooltipTimer.stop() 0501 showTooltip(false) 0502 } 0503 0504 onClicked: showTooltip(true, status, mouseAreaRect); 0505 onDoubleClicked: Activity.ackColor(index, colIndex); 0506 0507 } 0508 } 0509 0510 SearchItem { 0511 id: singleGuess 0512 0513 width: guessColumn.guessSize 0514 height: guessColumn.guessSize 0515 anchors.left: parent.left 0516 anchors.top: parent.top 0517 anchors.leftMargin: guessColumn.statusMargin 0518 anchors.topMargin: guessColumn.statusMargin 0519 0520 border.width: 2 0521 border.color: "#373737" 0522 searchItemIndex: colIndex 0523 opacity: 1.0 0524 z: 2 0525 0526 Image { 0527 id: okImage 0528 visible: isAcked 0529 0530 width: parent.width / 2 0531 height: parent.height / 2 0532 0533 anchors.centerIn: parent 0534 0535 source: "qrc:/gcompris/src/core/resource/apply.svg" 0536 } 0537 0538 MouseArea { 0539 id: ackMouseArea 0540 anchors.fill: parent 0541 acceptedButtons: Qt.LeftButton 0542 enabled: status == Activity.STATUS_UNKNOWN && !bonus.isPlaying 0543 visible: status == Activity.STATUS_UNKNOWN 0544 z: 3 0545 hoverEnabled: ApplicationInfo.isMobile ? false : true 0546 0547 onDoubleClicked: Activity.ackColor(index, colIndex); 0548 } 0549 } 0550 } 0551 } 0552 0553 Item { 0554 id: guessRowSpacer2 0555 width: 10 0556 height: guessColumn.guessSize 0557 } 0558 0559 Column { 0560 id: guessResultColumn 0561 0562 width: guessColumn.resultColWidth 0563 height: guessColumn.guessSize 0564 spacing: 2 0565 0566 Item { 0567 id: guessResultColSpacer 0568 width: guessResultColumn.width 0569 height: (guessResultColumn.height - 2 * (guessColumn.resultSize)) 0570 } 0571 0572 Row { 0573 id: guessResultCorrectRow 0574 0575 width: guessResultColumn.width 0576 height: guessColumn.resultSize 0577 spacing: 2 0578 0579 Repeater { 0580 id: guessResultCorrectRepeater 0581 0582 model: result.correct 0583 delegate: Rectangle { 0584 id: singleCorrectResult 0585 0586 width: guessColumn.resultSize 0587 height: guessColumn.resultSize 0588 0589 radius: width * 0.5 0590 border.width: 1 0591 border.color: "white" 0592 color: "black" 0593 } 0594 } 0595 } 0596 0597 Row { 0598 id: guessResultMisplacedRow 0599 0600 width: guessResultColumn.width 0601 height: guessColumn.resultSize 0602 spacing: 2 0603 0604 Repeater { 0605 id: guessResultMisplacedRepeater 0606 0607 model: result.misplaced 0608 delegate: Rectangle { 0609 id: singleMisplacedResult 0610 0611 width: guessColumn.resultSize 0612 height: guessColumn.resultSize 0613 0614 radius: width * 0.5 0615 border.width: 1 0616 border.color: "black" 0617 color: "white" 0618 } 0619 } 0620 } 0621 } 0622 } 0623 } 0624 0625 DialogHelp { 0626 id: dialogHelp 0627 onClose: home() 0628 } 0629 0630 DialogChooseLevel { 0631 id: dialogActivityConfig 0632 currentActivity: activity.activityInfo 0633 onClose: { 0634 home() 0635 } 0636 onLoadData: { 0637 if(activityData && activityData["mode"]) { 0638 items.mode = activityData["mode"]; 0639 } 0640 } 0641 } 0642 0643 Bar { 0644 id: bar 0645 level: items.currentLevel + 1 0646 content: BarEnumContent { value: help | home | level | activityConfig } 0647 onHelpClicked: { 0648 displayDialog(dialogHelp) 0649 } 0650 onPreviousLevelClicked: Activity.previousLevel() 0651 onNextLevelClicked: Activity.nextLevel() 0652 onHomeClicked: activity.home() 0653 onActivityConfigClicked: { 0654 displayDialog(dialogActivityConfig) 0655 } 0656 } 0657 0658 Bonus { 0659 id: bonus 0660 Component.onCompleted: win.connect(Activity.nextLevel) 0661 } 0662 0663 Score { 0664 id: score 0665 anchors.bottom: undefined 0666 anchors.rightMargin: 10 * ApplicationInfo.ratio 0667 anchors.topMargin: 10 * ApplicationInfo.ratio 0668 anchors.left: undefined 0669 anchors.top: parent.top 0670 anchors.right: parent.right 0671 onStop: Activity.nextSubLevel() 0672 } 0673 } 0674 }