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

0001 /* GCompris - MemoryCommon.qml
0002  *
0003  * SPDX-FileCopyrightText: 2014 JB BUTET <ashashiwa@gmail.com>
0004  *
0005  * Authors:
0006  *   Bruno Coudoin <bruno.coudoin@gcompris.net> (GTK+ version)
0007  *   JB BUTET <ashashiwa@gmail.com> (Qt Quick port)
0008  *
0009  *   SPDX-License-Identifier: GPL-3.0-or-later
0010  */
0011 import QtQuick 2.12
0012 import GCompris 1.0
0013 
0014 import "."
0015 import "../../core"
0016 import "memory.js" as Activity
0017 
0018 ActivityBase {
0019     id: activity
0020     focus: true
0021 
0022     property string backgroundImg
0023     property var dataset
0024     property bool withTux: false
0025     property bool needsVoices: false
0026 
0027     onStart: focus = true
0028     onStop: {}
0029 
0030     isMusicalActivity: needsVoices
0031 
0032     pageComponent: Image {
0033         id: background
0034         source: activity.backgroundImg
0035         sourceSize.width: width
0036         sourceSize.height: height
0037         fillMode: Image.PreserveAspectCrop
0038         focus: true
0039 
0040         signal start
0041         signal stop
0042 
0043         property alias items: items
0044         property bool keyNavigationVisible: false
0045         // if audio is disabled, we display a dialog to tell users this activity requires audio anyway
0046         property bool audioDisabled: false
0047         property bool horizontalLayout: layoutArea.width >= layoutArea.height
0048 
0049         Component.onCompleted: {
0050             dialogActivityConfig.initialize()
0051             activity.start.connect(start)
0052             activity.stop.connect(stop)
0053         }
0054 
0055         QtObject {
0056             id: items
0057             property int currentLevel: activity.currentLevel
0058             property alias bonus: bonus
0059             property GCSfx audioEffects: activity.audioEffects
0060             property bool withTux: activity.withTux
0061             property int playerCount: 1
0062             property bool tuxTurn: false
0063             property bool player2Turn: false
0064             property alias player1Score: player1Score
0065             property alias player2Score: player2Score
0066             property var playQueue
0067             property int selectionCount
0068             readonly property var levels: activity.datasetLoader.data !=  0 ? activity.datasetLoader.data : activity.dataset
0069             property alias containerModel: containerModel
0070             property alias grid: grid
0071             property bool blockClicks: false
0072             property int columns
0073             property int rows
0074             property int spacing: 5 * ApplicationInfo.ratio
0075             property bool isMultipleDatasetMode: activity.datasetLoader.data != 0
0076         }
0077 
0078         onStart: {
0079             Activity.start(items);
0080             if(activity.needsVoices === true) {
0081                 if(!ApplicationSettings.isAudioVoicesEnabled || !ApplicationSettings.isAudioEffectsEnabled)
0082                     background.audioDisabled = true
0083             }
0084         }
0085 
0086         onStop: {
0087             Activity.stop();
0088         }
0089 
0090         ListModel {
0091             id: containerModel
0092         }
0093 
0094         Item {
0095             id: layoutArea
0096             anchors.top: background.top
0097             anchors.bottom: bar.top
0098             anchors.left: background.left
0099             anchors.right: background.right
0100             anchors.margins: items.spacing
0101         }
0102 
0103         GridView {
0104             id: grid
0105             cellWidth: width / items.columns
0106             cellHeight: height / items.rows
0107             anchors {
0108                 left: background.left
0109                 right: player1Score.left
0110                 top: background.top
0111                 bottom: player1Score.bottom
0112                 margins: items.spacing
0113             }
0114 
0115             model: containerModel
0116 
0117             function getItemAtIndex(i) {
0118                 var xi = (i % items.columns) * cellWidth + anchors.margins
0119                 var yi = (i / items.columns) * cellHeight + anchors.margins
0120                 return itemAt(xi, yi)
0121             }
0122 
0123             delegate: CardItem {
0124                 pairData: pairData_
0125                 tuxTurn: background.items.tuxTurn
0126                 width: grid.cellWidth - grid.anchors.margins
0127                 height: grid.cellHeight - grid.anchors.margins
0128                 audioVoices: activity.audioVoices
0129                 audioEffects: activity.audioEffects
0130                 onIsFoundChanged: background.keyNavigationVisible = false
0131             }
0132             interactive: false
0133             highlightFollowsCurrentItem: true
0134             highlightMoveDuration: 0
0135             highlight: Rectangle {
0136                 color: "#D0FFFFFF"
0137                 radius: 10
0138                 scale: 1.1
0139                 visible: background.keyNavigationVisible
0140             }
0141             add: Transition {
0142                 PathAnimation {
0143                     path: Path {
0144                         PathCurve { x: 0; y: 0}
0145                         PathCurve {}
0146                     }
0147                     easing.type: Easing.InOutQuad
0148                     duration: 1000
0149                 }
0150             }
0151         }
0152 
0153         DialogHelp {
0154             id: dialogHelp
0155             onClose: home()
0156         }
0157 
0158         DialogChooseLevel {
0159             id: dialogActivityConfig
0160             currentActivity: activity.activityInfo
0161 
0162             onSaveData: {
0163                 levelFolder = dialogActivityConfig.chosenLevels
0164                 currentActivity.currentLevels = dialogActivityConfig.chosenLevels
0165                 ApplicationSettings.setCurrentLevels(currentActivity.name, dialogActivityConfig.chosenLevels)
0166             }
0167 
0168             onLoadData: {
0169                  if(activityData && activityData["mode"]) {
0170                        items.playerCount = activityData["mode"];
0171                   }
0172             }
0173 
0174             onClose: {
0175                 home()
0176             }
0177             onStartActivity: {
0178                 background.stop()
0179                 background.start()
0180             }
0181         }
0182 
0183 
0184         Bar {
0185             id: bar
0186             level: items.currentLevel + 1
0187             content: BarEnumContent { value: (activity.activityInfo.hasConfig || items.isMultipleDatasetMode) ? (help | home | level | activityConfig ) : (help | home | level ) }
0188             onHelpClicked: {
0189                 displayDialog(dialogHelp)
0190             }
0191             onPreviousLevelClicked: Activity.previousLevel()
0192             onActivityConfigClicked: {
0193                 displayDialog(dialogActivityConfig)
0194             }
0195             onNextLevelClicked: Activity.nextLevel()
0196             onHomeClicked: home()
0197         }
0198 
0199         ScoreItem {
0200             id: player1Score
0201             height: Math.min(background.height/7, Math.min(background.width/7, bar.height * 1.05))
0202             width: height * 1.2
0203             anchors {
0204                 bottom: bar.top
0205                 right: background.right
0206                 rightMargin: items.spacing * 8
0207                 bottomMargin: items.spacing * 6
0208             }
0209             playerImageSource: 'qrc:/gcompris/src/activities/memory/resource/child.svg'
0210             backgroundImageSource: 'qrc:/gcompris/src/activities/bargame/resource/score_1.svg'
0211         }
0212 
0213         ScoreItem {
0214             id: player2Score
0215             height: Math.min(background.height/7, Math.min(background.width/7, bar.height * 1.05))
0216             width: height * 1.2
0217             visible: activity.withTux || items.playerCount == 2
0218             anchors {
0219                 bottom: player1Score.top
0220                 right: background.right
0221                 rightMargin: items.spacing * 8
0222                 bottomMargin: items.spacing * 6
0223             }
0224             playerImageSource: 'qrc:/gcompris/src/activities/memory/resource/tux.svg'
0225             backgroundImageSource: 'qrc:/gcompris/src/activities/bargame/resource/score_2.svg'
0226         }
0227 
0228 
0229         states: [
0230             State {
0231                 name: "horizontalCards"
0232                 when: horizontalLayout
0233                 AnchorChanges {
0234                     target: player2Score
0235                     anchors.bottom: player1Score.top
0236                     anchors.right: background.right
0237                 }
0238                 AnchorChanges {
0239                     target: grid
0240                     anchors.bottom: player1Score.bottom
0241                     anchors.right: player1Score.left
0242                 }
0243 
0244             },
0245             State {
0246                 name: "verticalCards"
0247                 when: !horizontalLayout
0248                 AnchorChanges {
0249                     target: player2Score
0250                     anchors.bottom: bar.top
0251                     anchors.right: player1Score.left
0252                 }
0253                 AnchorChanges {
0254                     target: grid
0255                     anchors.bottom: player1Score.top
0256                     anchors.right: background.right
0257                 }
0258             }
0259         ]
0260 
0261         Bonus {
0262             id: bonus
0263             interval: 2000
0264             Component.onCompleted: {
0265                 win.connect(Activity.nextLevel)
0266                 loose.connect(Activity.repeatCurrentLevel)
0267             }
0268         }
0269 
0270         Keys.enabled: !items.blockClicks
0271         Keys.onPressed: {
0272             background.keyNavigationVisible = true
0273             if(event.key === Qt.Key_Left) {
0274                 do {
0275                     if(grid.currentIndex <= 0) {
0276                         grid.currentIndex = grid.count - 1;
0277                     } else {
0278                         grid.currentIndex -= 1;
0279                     }
0280                 }
0281                 while(grid.currentItem.isFound && !items.blockClicks)
0282             }
0283             else if(event.key === Qt.Key_Right) {
0284                 do {
0285                     if(grid.currentIndex >= grid.count - 1) {
0286                         grid.currentIndex = 0;
0287                     } else {
0288                         grid.currentIndex += 1
0289                     }
0290                 }
0291                 while(grid.currentItem.isFound && !items.blockClicks)
0292             }
0293             else if(event.key === Qt.Key_Up) {
0294                 do {
0295                     if(grid.currentIndex === 0) {
0296                         grid.currentIndex = grid.count - 1
0297                     } else {
0298                         grid.currentIndex -= items.columns
0299                         if(grid.currentIndex < 0)
0300                             grid.currentIndex += grid.count - 1
0301                     }
0302                 }
0303                 while(grid.currentItem.isFound && !items.blockClicks)
0304             }
0305             else if(event.key === Qt.Key_Down) {
0306                 do {
0307                     if(grid.currentIndex === grid.count - 1) {
0308                         grid.currentIndex = 0
0309                     } else {
0310                         grid.currentIndex += items.columns
0311                         if(grid.currentIndex >= grid.count)
0312                             grid.currentIndex -= grid.count - 1
0313                     }
0314                 }
0315                 while(grid.currentItem.isFound && !items.blockClicks)
0316             }
0317             else if(event.key === Qt.Key_Space || event.key === Qt.Key_Enter || event.key === Qt.Key_Return)
0318                 if(grid.currentItem.isBack && !grid.currentItem.isFound && !grid.currentItem.tuxTurn && items.selectionCount < 2) grid.currentItem.selected()
0319         }
0320 
0321         Loader {
0322             id: audioNeededDialog
0323             sourceComponent: GCDialog {
0324                 parent: activity
0325                 isDestructible: false
0326                 message: qsTr("This activity requires sound, so it will play some sounds even if the audio voices or effects are disabled in the main configuration.")
0327                 button1Text: qsTr("Quit")
0328                 button2Text: qsTr("Continue")
0329                 onButton1Hit: activity.home();
0330                 onClose: {
0331                     background.audioDisabled = false;
0332                 }
0333             }
0334             anchors.fill: parent
0335             focus: true
0336             active: background.audioDisabled
0337             onStatusChanged: if (status == Loader.Ready) item.start()
0338         }
0339     }
0340 }