Warning, /education/gcompris/src/activities/note_names/NoteNames.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - NoteNames.qml 0002 * 0003 * SPDX-FileCopyrightText: 2018 Aman Kumar Gupta <gupta2140@gmail.com> 0004 * 0005 * Authors: 0006 * Aman Kumar Gupta <gupta2140@gmail.com> 0007 * 0008 * SPDX-License-Identifier: GPL-3.0-or-later 0009 */ 0010 import QtQuick 2.12 0011 import QtQuick.Controls 2.12 0012 import GCompris 1.0 0013 0014 import "../../core" 0015 import "../piano_composition" 0016 import "note_names.js" as Activity 0017 0018 ActivityBase { 0019 id: activity 0020 property int speedSetting: 5 0021 property int timerNormalInterval: (13500 / speedSetting) 0022 isMusicalActivity: true 0023 0024 onStart: focus = true 0025 onStop: {} 0026 0027 property bool horizontalLayout: width >= height 0028 0029 pageComponent: Rectangle { 0030 id: background 0031 anchors.fill: parent 0032 color: "#ABCDEF" 0033 signal start 0034 signal stop 0035 0036 // if audio is disabled, we display a dialog to tell users this activity requires audio anyway 0037 property bool audioDisabled: false 0038 0039 Component.onCompleted: { 0040 dialogActivityConfig.initialize() 0041 activity.start.connect(start) 0042 activity.stop.connect(stop) 0043 } 0044 0045 // Needed to get keyboard focus on IntroMessage 0046 Keys.forwardTo: introMessage 0047 0048 Keys.onPressed: { 0049 var keyNoteBindings = {} 0050 keyNoteBindings[Qt.Key_1] = 'C' 0051 keyNoteBindings[Qt.Key_2] = 'D' 0052 keyNoteBindings[Qt.Key_3] = 'E' 0053 keyNoteBindings[Qt.Key_4] = 'F' 0054 keyNoteBindings[Qt.Key_5] = 'G' 0055 keyNoteBindings[Qt.Key_6] = 'A' 0056 keyNoteBindings[Qt.Key_7] = 'B' 0057 0058 if(!introMessage.visible && !iAmReady.visible && !messageBox.visible && multipleStaff.musicElementModel.count - 1) { 0059 if(keyNoteBindings[event.key]) { 0060 // If the key pressed matches the note, pass the correct answer as parameter. 0061 isCorrectKey(keyNoteBindings[event.key]) 0062 } 0063 else if(event.key === Qt.Key_Left && shiftKeyboardLeft.visible) { 0064 doubleOctave.currentOctaveNb-- 0065 } 0066 else if(event.key === Qt.Key_Right && shiftKeyboardRight.visible) { 0067 doubleOctave.currentOctaveNb++ 0068 } 0069 } 0070 } 0071 0072 function isCorrectKey(key) { 0073 if(Activity.newNotesSequence[Activity.currentNoteIndex][0] === key) 0074 Activity.correctAnswer() 0075 else 0076 items.displayNoteNameTimer.start() 0077 } 0078 0079 // Add here the QML items you need to access in javascript 0080 QtObject { 0081 id: items 0082 property Item main: activity.main 0083 property alias background: background 0084 property GCSfx audioEffects: activity.audioEffects 0085 property int currentLevel: activity.currentLevel 0086 property alias multipleStaff: multipleStaff 0087 property alias doubleOctave: doubleOctave 0088 property alias bonus: bonus 0089 property alias iAmReady: iAmReady 0090 property alias messageBox: messageBox 0091 property alias addNoteTimer: addNoteTimer 0092 property alias dataset: dataset 0093 property alias progressBar: progressBar 0094 property alias introMessage: introMessage 0095 property bool isTutorialMode: true 0096 property alias displayNoteNameTimer: displayNoteNameTimer 0097 } 0098 0099 Loader { 0100 id: dataset 0101 asynchronous: false 0102 source: "qrc:/gcompris/src/activities/note_names/resource/dataset_01.qml" 0103 } 0104 0105 onStart: { 0106 if(!ApplicationSettings.isAudioVoicesEnabled || !ApplicationSettings.isAudioEffectsEnabled) { 0107 introMessage.index = -1; 0108 background.audioDisabled = true; 0109 } 0110 Activity.start(items, activity.timerNormalInterval); 0111 } 0112 onStop: { Activity.stop() } 0113 0114 property string clefType: "Treble" 0115 0116 DialogChooseLevel { 0117 id: dialogActivityConfig 0118 currentActivity: activity.activityInfo 0119 0120 onStartActivity: { 0121 introMessage.visible = false; 0122 iAmReady.visible = true; 0123 } 0124 onClose: { 0125 home(); 0126 introMessage.visible = false; 0127 iAmReady.visible = true; 0128 } 0129 onLoadData: { 0130 if(activityData && activityData["speedSetting"]) { 0131 activity.speedSetting = activityData["speedSetting"]; 0132 } 0133 } 0134 } 0135 0136 Timer { 0137 id: displayNoteNameTimer 0138 interval: 2000 0139 onRunningChanged: { 0140 if(running) { 0141 multipleStaff.pauseNoteAnimation() 0142 addNoteTimer.pause() 0143 messageBox.visible = true 0144 } 0145 else { 0146 messageBox.visible = false 0147 if(progressBar.percentage != 100 && Activity.newNotesSequence.length) { 0148 Activity.wrongAnswer() 0149 addNoteTimer.resume() 0150 } 0151 } 0152 } 0153 } 0154 0155 Rectangle { 0156 id: messageBox 0157 width: label.width + 20 0158 height: label.height + 20 0159 border.width: 5 0160 border.color: "black" 0161 anchors.centerIn: multipleStaff 0162 radius: 10 0163 z: 11 0164 visible: false 0165 0166 function getTranslatedNoteName(noteName) { 0167 for(var i = 0; i < doubleOctave.keyNames.length; i++) { 0168 if(doubleOctave.keyNames[i][0] == noteName) 0169 return doubleOctave.keyNames[i][1] 0170 } 0171 return "" 0172 } 0173 0174 onVisibleChanged: { 0175 if(Activity.targetNotes[0] === undefined) 0176 text = "" 0177 else if(items.isTutorialMode) 0178 text = qsTr("New note: %1").arg(getTranslatedNoteName(Activity.targetNotes[0])) 0179 else 0180 text = getTranslatedNoteName(Activity.newNotesSequence[Activity.currentNoteIndex]) 0181 } 0182 0183 property string text 0184 0185 GCText { 0186 id: label 0187 anchors.centerIn: parent 0188 fontSize: mediumSize 0189 text: parent.text 0190 } 0191 0192 MouseArea { 0193 anchors.fill: parent 0194 enabled: items.isTutorialMode 0195 onClicked: { 0196 items.multipleStaff.pauseNoteAnimation() 0197 items.multipleStaff.musicElementModel.remove(1) 0198 Activity.showTutorial() 0199 } 0200 } 0201 } 0202 0203 Rectangle { 0204 id: colorLayer 0205 anchors.fill: parent 0206 color: "black" 0207 opacity: 0.3 0208 visible: iAmReady.visible 0209 z: 10 0210 MouseArea { 0211 anchors.fill: parent 0212 } 0213 } 0214 0215 ReadyButton { 0216 id: iAmReady 0217 focus: true 0218 z: 10 0219 visible: !introMessage.visible 0220 onVisibleChanged: { 0221 messageBox.visible = false 0222 } 0223 onClicked: { 0224 Activity.initLevel() 0225 } 0226 } 0227 0228 IntroMessage { 0229 id: introMessage 0230 anchors { 0231 top: parent.top 0232 topMargin: 10 0233 right: parent.right 0234 rightMargin: 5 0235 left: parent.left 0236 leftMargin: 5 0237 } 0238 z: 12 0239 } 0240 0241 AdvancedTimer { 0242 id: addNoteTimer 0243 onTriggered: { 0244 Activity.noteIndexToDisplay = (Activity.noteIndexToDisplay + 1) % Activity.newNotesSequence.length 0245 Activity.displayNote(Activity.newNotesSequence[Activity.noteIndexToDisplay]) 0246 } 0247 } 0248 0249 GCProgressBar { 0250 id: progressBar 0251 height: 20 * ApplicationInfo.ratio 0252 width: parent.width / 4 0253 0254 property int percentage: 0 0255 0256 value: percentage 0257 to: 100 0258 visible: !items.isTutorialMode 0259 anchors { 0260 top: parent.top 0261 topMargin: 10 0262 right: parent.right 0263 rightMargin: 10 0264 } 0265 //: The following translation represents percentage. 0266 message: qsTr("%1%").arg(value) 0267 } 0268 0269 MultipleStaff { 0270 id: multipleStaff 0271 width: horizontalLayout ? parent.width * 0.5 : parent.width * 0.78 0272 height: horizontalLayout ? parent.height * 0.9 : parent.height * 0.7 0273 nbStaves: 1 0274 clef: clefType 0275 notesColor: "red" 0276 softColorOpacity: 0 0277 isFlickable: false 0278 anchors.horizontalCenter: parent.horizontalCenter 0279 anchors.top: parent.top 0280 anchors.topMargin: progressBar.height + 20 0281 flickableTopMargin: multipleStaff.height / 14 + distanceBetweenStaff / 2.7 0282 noteAnimationEnabled: true 0283 noteAnimationDuration: items.isTutorialMode ? 9000 : 45000 / activity.speedSetting 0284 onNoteAnimationFinished: { 0285 if(!items.isTutorialMode) 0286 displayNoteNameTimer.start() 0287 } 0288 } 0289 0290 // We present a pair of two joint piano keyboard octaves. 0291 Item { 0292 id: doubleOctave 0293 width: parent.width * 0.95 0294 height: horizontalLayout ? parent.height * 0.22 : 2 * parent.height * 0.18 0295 anchors.horizontalCenter: parent.horizontalCenter 0296 anchors.bottom: bar.top 0297 anchors.bottomMargin: 30 0298 0299 readonly property int nbJointKeyboards: 2 0300 readonly property int maxNbOctaves: 3 0301 property int currentOctaveNb: 0 0302 property var coloredKeyLabels: [] 0303 property var keyNames: [] 0304 0305 Repeater { 0306 id: octaveRepeater 0307 anchors.fill: parent 0308 model: doubleOctave.nbJointKeyboards 0309 PianoOctaveKeyboard { 0310 id: pianoKeyboard 0311 width: horizontalLayout ? octaveRepeater.width / 2 : octaveRepeater.width 0312 height: horizontalLayout ? octaveRepeater.height : octaveRepeater.height / 2 0313 blackLabelsVisible: false 0314 blackKeysEnabled: blackLabelsVisible 0315 whiteKeysEnabled: !messageBox.visible && multipleStaff.musicElementModel.count > 1 0316 onNoteClicked: Activity.checkAnswer(note) 0317 currentOctaveNb: doubleOctave.currentOctaveNb 0318 anchors.top: (index === 1) ? octaveRepeater.top : undefined 0319 anchors.topMargin: horizontalLayout ? 0 : -15 0320 anchors.bottom: (index === 0) ? octaveRepeater.bottom : undefined 0321 anchors.right: (index === 1) ? octaveRepeater.right : undefined 0322 coloredKeyLabels: doubleOctave.coloredKeyLabels 0323 labelsColor: "red" 0324 // The octaves sets corresponding to respective clef types are in pairs for the joint piano keyboards at a time when displaying. 0325 whiteKeyNoteLabelsBass: { 0326 if(index === 0) { 0327 return [ 0328 whiteKeyNoteLabelsArray.slice(0, 4), // F1 to B1 0329 whiteKeyNoteLabelsArray.slice(4, 11), // C2 to B2 0330 whiteKeyNoteLabelsArray.slice(11, 18) // C3 to B3 0331 ] 0332 } 0333 else { 0334 return [ 0335 whiteKeyNoteLabelsArray.slice(4, 11), // C2 to B2 0336 whiteKeyNoteLabelsArray.slice(11, 18), // C3 to B3 0337 whiteKeyNoteLabelsArray.slice(18, 25) // C4 to B4 0338 ] 0339 } 0340 } 0341 whiteKeyNoteLabelsTreble: { 0342 if(index === 0) { 0343 return [ 0344 whiteKeyNoteLabelsArray.slice(11, 18), // C3 to B3 0345 whiteKeyNoteLabelsArray.slice(18, 25), // C4 to B4 0346 whiteKeyNoteLabelsArray.slice(25, 32) // C5 to B5 0347 ] 0348 } 0349 else { 0350 return [ 0351 whiteKeyNoteLabelsArray.slice(18, 25), // C4 to B4 0352 whiteKeyNoteLabelsArray.slice(25, 32), // C5 to B5 0353 whiteKeyNoteLabelsArray.slice(32, 34) // C6 to D6 0354 ] 0355 } 0356 } 0357 0358 Component.onCompleted: doubleOctave.keyNames = whiteKeyNoteLabelsArray 0359 } 0360 } 0361 } 0362 0363 Image { 0364 id: shiftKeyboardLeft 0365 source: "qrc:/gcompris/src/core/resource/bar_previous.svg" 0366 sourceSize.width: horizontalLayout ? doubleOctave.width / 13 : doubleOctave.width / 6 0367 width: sourceSize.width 0368 height: width 0369 fillMode: Image.PreserveAspectFit 0370 visible: (doubleOctave.currentOctaveNb > 0) && doubleOctave.visible 0371 z: 11 0372 anchors { 0373 bottom: doubleOctave.top 0374 left: doubleOctave.left 0375 leftMargin: -37 0376 bottomMargin: horizontalLayout ? 10 : 25 0377 } 0378 MouseArea { 0379 enabled: !messageBox.visible 0380 anchors.fill: parent 0381 onClicked: { 0382 doubleOctave.currentOctaveNb-- 0383 } 0384 } 0385 } 0386 0387 Image { 0388 id: shiftKeyboardRight 0389 source: "qrc:/gcompris/src/core/resource/bar_next.svg" 0390 sourceSize.width: horizontalLayout ? doubleOctave.width / 13 : doubleOctave.width / 6 0391 width: sourceSize.width 0392 height: width 0393 fillMode: Image.PreserveAspectFit 0394 visible: (doubleOctave.currentOctaveNb < doubleOctave.maxNbOctaves - 1) && doubleOctave.visible 0395 z: 11 0396 anchors { 0397 bottom: doubleOctave.top 0398 right: doubleOctave.right 0399 rightMargin: -37 0400 bottomMargin: horizontalLayout ? 10 : 25 0401 } 0402 MouseArea { 0403 enabled: !messageBox.visible 0404 anchors.fill: parent 0405 onClicked: { 0406 doubleOctave.currentOctaveNb++ 0407 } 0408 } 0409 } 0410 0411 OptionsRow { 0412 id: optionsRow 0413 iconsWidth: 0 0414 visible: false 0415 } 0416 0417 DialogHelp { 0418 id: dialogHelp 0419 onClose: home() 0420 } 0421 0422 Bar { 0423 id: bar 0424 level: items.currentLevel + 1 0425 content: BarEnumContent { value: (help | home | level | reload | activityConfig) } 0426 onHelpClicked: { 0427 displayDialog(dialogHelp) 0428 } 0429 onPreviousLevelClicked: Activity.previousLevel() 0430 onNextLevelClicked: Activity.nextLevel() 0431 onHomeClicked: home() 0432 onActivityConfigClicked: { 0433 multipleStaff.pauseNoteAnimation() 0434 addNoteTimer.pause() 0435 displayDialog(dialogActivityConfig) 0436 } 0437 onReloadClicked: { 0438 iAmReady.visible = true 0439 Activity.initLevel() 0440 } 0441 } 0442 0443 Bonus { 0444 id: bonus 0445 Component.onCompleted: win.connect(Activity.nextLevel) 0446 } 0447 0448 Loader { 0449 id: audioNeededDialog 0450 sourceComponent: GCDialog { 0451 parent: activity 0452 isDestructible: false 0453 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.") 0454 button1Text: qsTr("Quit") 0455 button2Text: qsTr("Continue") 0456 onButton1Hit: activity.home(); 0457 onClose: { 0458 background.audioDisabled = false; 0459 introMessage.index = 0; 0460 } 0461 } 0462 anchors.fill: parent 0463 focus: true 0464 active: background.audioDisabled 0465 onStatusChanged: if (status == Loader.Ready) item.start() 0466 } 0467 } 0468 }