Warning, /education/gcompris/src/activities/play_piano/PlayPiano.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - PlayPiano.qml 0002 * 0003 * SPDX-FileCopyrightText: 2018 Aman Kumar Gupta <gupta2140@gmail.com> 0004 * 0005 * Authors: 0006 * Beth Hadley <bethmhadley@gmail.com> (GTK+ version) 0007 * Aman Kumar Gupta <gupta2140@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 "../../core" 0015 import "../piano_composition" 0016 import "play_piano.js" as Activity 0017 0018 ActivityBase { 0019 id: activity 0020 0021 onStart: focus = true 0022 onStop: {} 0023 isMusicalActivity: true 0024 0025 property bool horizontalLayout: width >= height * 1.2 0026 0027 pageComponent: Rectangle { 0028 id: background 0029 anchors.fill: parent 0030 color: "#ABCDEF" 0031 signal start 0032 signal stop 0033 0034 // if audio is disabled, we display a dialog to tell users this activity requires audio anyway 0035 property bool audioDisabled: false 0036 0037 Component.onCompleted: { 0038 dialogActivityConfig.initialize() 0039 activity.start.connect(start) 0040 activity.stop.connect(stop) 0041 } 0042 0043 Keys.onPressed: { 0044 if(items.buttonsBlocked) 0045 return; 0046 0047 var keyboardBindings = {} 0048 keyboardBindings[Qt.Key_1] = 0 0049 keyboardBindings[Qt.Key_2] = 1 0050 keyboardBindings[Qt.Key_3] = 2 0051 keyboardBindings[Qt.Key_4] = 3 0052 keyboardBindings[Qt.Key_5] = 4 0053 keyboardBindings[Qt.Key_6] = 5 0054 keyboardBindings[Qt.Key_7] = 6 0055 keyboardBindings[Qt.Key_8] = 7 0056 keyboardBindings[Qt.Key_F2] = 1 0057 keyboardBindings[Qt.Key_F3] = 2 0058 keyboardBindings[Qt.Key_F5] = 4 0059 keyboardBindings[Qt.Key_F6] = 5 0060 keyboardBindings[Qt.Key_F7] = 6 0061 0062 if(piano.whiteKeysEnabled && !iAmReady.visible) { 0063 if(event.key >= Qt.Key_1 && event.key <= Qt.Key_8) { 0064 piano.keyRepeater.playKey(keyboardBindings[event.key], "white"); 0065 } 0066 else if(event.key >= Qt.Key_F2 && event.key <= Qt.Key_F7) { 0067 if(piano.blackKeysEnabled) 0068 piano.keyRepeater.playKey(keyboardBindings[event.key], "black"); 0069 } 0070 else if(event.key === Qt.Key_Space) { 0071 multipleStaff.play() 0072 } 0073 else if(event.key === Qt.Key_Backspace || event.key === Qt.Key_Delete) { 0074 Activity.undoPreviousAnswer() 0075 } 0076 } else if(iAmReady.visible) { 0077 iAmReady.visible = false; 0078 iAmReady.clicked(); 0079 } 0080 } 0081 0082 // Add here the QML items you need to access in javascript 0083 QtObject { 0084 id: items 0085 property Item main: activity.main 0086 property alias background: background 0087 property GCSfx audioEffects: activity.audioEffects 0088 property alias multipleStaff: multipleStaff 0089 property alias piano: piano 0090 property int currentLevel: activity.currentLevel 0091 property alias bonus: bonus 0092 property alias score: score 0093 property alias iAmReady: iAmReady 0094 property alias introductoryAudioTimer: introductoryAudioTimer 0095 property alias parser: parser 0096 property alias answerFeedbackTimer: answerFeedbackTimer 0097 property string mode: "coloredNotes" 0098 property bool buttonsBlocked: false 0099 } 0100 0101 onStart: { 0102 if(!ApplicationSettings.isAudioVoicesEnabled || !ApplicationSettings.isAudioEffectsEnabled) { 0103 background.audioDisabled = true; 0104 } 0105 Activity.start(items); 0106 } 0107 onStop: { Activity.stop() } 0108 0109 property string clefType: (items.bar.level <= 5) ? "Treble" : "Bass" 0110 0111 Timer { 0112 id: introductoryAudioTimer 0113 interval: 4000 0114 onRunningChanged: { 0115 if(running) 0116 Activity.isIntroductoryAudioPlaying = true 0117 else { 0118 Activity.isIntroductoryAudioPlaying = false 0119 Activity.initSubLevel() 0120 } 0121 } 0122 } 0123 0124 Timer { 0125 id: answerFeedbackTimer 0126 interval: 1000 0127 onRunningChanged: { 0128 if(!running) 0129 Activity.answerFeedback() 0130 } 0131 } 0132 0133 JsonParser { 0134 id: parser 0135 } 0136 0137 Rectangle { 0138 anchors.fill: parent 0139 color: "black" 0140 opacity: 0.3 0141 visible: iAmReady.visible 0142 z: 10 0143 MouseArea { 0144 anchors.fill: parent 0145 } 0146 } 0147 0148 ReadyButton { 0149 id: iAmReady 0150 focus: true 0151 z: 10 0152 onClicked: { 0153 Activity.initLevel() 0154 } 0155 } 0156 0157 Score { 0158 id: score 0159 anchors.top: background.top 0160 anchors.bottom: undefined 0161 numberOfSubLevels: 5 0162 width: horizontalLayout ? parent.width / 10 : (parent.width - instruction.x - instruction.width - 1.5 * anchors.rightMargin) 0163 onStop: Activity.nextSubLevel() 0164 } 0165 0166 Rectangle { 0167 id: instruction 0168 radius: 10 0169 width: background.width * 0.6 0170 height: background.height / 9 0171 anchors.horizontalCenter: parent.horizontalCenter 0172 opacity: 0.8 0173 border.width: 6 0174 color: "white" 0175 border.color: "#87A6DD" 0176 0177 GCText { 0178 color: "black" 0179 z: 3 0180 anchors.fill: parent 0181 anchors.rightMargin: parent.width * 0.02 0182 anchors.leftMargin: parent.width * 0.02 0183 horizontalAlignment: Text.AlignHCenter 0184 verticalAlignment: Text.AlignVCenter 0185 fontSizeMode: Text.Fit 0186 wrapMode: Text.WordWrap 0187 text: qsTr("Click on the piano keys that match the given notes.") 0188 } 0189 } 0190 0191 MultipleStaff { 0192 id: multipleStaff 0193 width: horizontalLayout ? parent.width * 0.5 : parent.width * 0.8 0194 height: horizontalLayout ? parent.height * 0.85 : parent.height * 0.58 0195 nbStaves: 1 0196 clef: clefType 0197 coloredNotes: (items.mode === "coloredNotes") ? ['C', 'D', 'E', 'F', 'G', 'A', 'B'] : [] 0198 isFlickable: false 0199 anchors.horizontalCenter: parent.horizontalCenter 0200 anchors.top: instruction.bottom 0201 anchors.topMargin: horizontalLayout ? parent.height * 0.02 : parent.height * 0.15 0202 onNoteClicked: { 0203 playNoteAudio(musicElementModel.get(noteIndex).noteName_, musicElementModel.get(noteIndex).noteType_, musicElementModel.get(noteIndex).soundPitch_) 0204 } 0205 centerNotesPosition: true 0206 } 0207 0208 PianoOctaveKeyboard { 0209 id: piano 0210 width: horizontalLayout ? parent.width * 0.5 : parent.width * 0.7 0211 height: parent.height * 0.3 0212 anchors.horizontalCenter: parent.horizontalCenter 0213 anchors.bottom: bar.top 0214 anchors.bottomMargin: 20 0215 blackLabelsVisible: ([4, 5, 9, 10].indexOf(bar.level) != -1) 0216 blackKeysEnabled: blackLabelsVisible && !multipleStaff.isMusicPlaying && !introductoryAudioTimer.running && !items.buttonsBlocked 0217 whiteKeysEnabled: !multipleStaff.isMusicPlaying && !introductoryAudioTimer.running && !items.buttonsBlocked 0218 whiteKeyNoteLabelsTreble: [ whiteKeyNoteLabelsArray.slice(18, 26) ] 0219 whiteKeyNoteLabelsBass: [ whiteKeyNoteLabelsArray.slice(11, 19)] 0220 onNoteClicked: { 0221 multipleStaff.playNoteAudio(note, "Quarter", clefType, 500) 0222 Activity.checkAnswer(note) 0223 } 0224 useSharpNotation: true 0225 playPianoActivity: true 0226 } 0227 0228 Rectangle { 0229 id: optionDeck 0230 width: optionsRow.changeAccidentalStyleButtonVisible ? optionsRow.iconsWidth * 3.3 : optionsRow.iconsWidth * 2.2 0231 height: optionsRow.iconsWidth * 1.1 0232 color: "white" 0233 opacity: 0.5 0234 radius: 10 0235 y: horizontalLayout ? piano.y : multipleStaff.y / 2 + instruction.height - height / 2 0236 x: horizontalLayout ? multipleStaff.x + multipleStaff.width + 25 : background.width / 2 - width / 2 0237 } 0238 0239 OptionsRow { 0240 id: optionsRow 0241 anchors.centerIn: optionDeck 0242 0243 playButtonVisible: true 0244 undoButtonVisible: true 0245 0246 onUndoButtonClicked: Activity.undoPreviousAnswer() 0247 } 0248 MouseArea { 0249 id: optionsRowLock 0250 anchors.fill: optionsRow 0251 enabled: items.buttonsBlocked 0252 } 0253 0254 DialogChooseLevel { 0255 id: dialogActivityConfig 0256 currentActivity: activity.activityInfo 0257 0258 onClose: { 0259 home() 0260 } 0261 onLoadData: { 0262 if(activityData && activityData["mode"]) { 0263 items.mode = activityData["mode"]; 0264 } 0265 } 0266 onVisibleChanged: { 0267 multipleStaff.eraseAllNotes() 0268 iAmReady.visible = true 0269 } 0270 } 0271 0272 DialogHelp { 0273 id: dialogHelp 0274 onClose: home() 0275 } 0276 0277 Bar { 0278 id: bar 0279 level: items.currentLevel + 1 0280 content: BarEnumContent { value: help | home | level | activityConfig } 0281 onHelpClicked: displayDialog(dialogHelp) 0282 onPreviousLevelClicked: Activity.previousLevel() 0283 onNextLevelClicked: Activity.nextLevel() 0284 onHomeClicked: activity.home() 0285 onActivityConfigClicked: { 0286 displayDialog(dialogActivityConfig) 0287 } 0288 } 0289 0290 Bonus { 0291 id: bonus 0292 Component.onCompleted: win.connect(Activity.nextLevel) 0293 } 0294 0295 Loader { 0296 id: audioNeededDialog 0297 sourceComponent: GCDialog { 0298 parent: activity 0299 isDestructible: false 0300 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.") 0301 button1Text: qsTr("Quit") 0302 button2Text: qsTr("Continue") 0303 onButton1Hit: activity.home(); 0304 onClose: { 0305 background.audioDisabled = false; 0306 } 0307 } 0308 anchors.fill: parent 0309 focus: true 0310 active: background.audioDisabled 0311 onStatusChanged: if (status == Loader.Ready) item.start() 0312 } 0313 } 0314 }