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 }