Warning, /education/gcompris/src/activities/piano_composition/MusicElement.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - musicElement.qml 0002 * 0003 * SPDX-FileCopyrightText: 2016 Johnny Jazeix <jazeix@gmail.com> 0004 * SPDX-FileCopyrightText: 2018 Aman Kumar Gupta <gupta2140@gmail.com> 0005 * 0006 * Authors: 0007 * Beth Hadley <bethmhadley@gmail.com> (GTK+ version) 0008 * Johnny Jazeix <jazeix@gmail.com> (Qt Quick port) 0009 * Aman Kumar Gupta <gupta2140@gmail.com> (Qt Quick port) 0010 * 0011 * SPDX-License-Identifier: GPL-3.0-or-later 0012 */ 0013 import QtQuick 2.12 0014 import QtGraphicalEffects 1.0 0015 import GCompris 1.0 0016 0017 import "../../core" 0018 0019 Item { 0020 id: musicElement 0021 width: noteImageWidth 0022 height: multipleStaff.height / 5 0023 0024 signal stop 0025 0026 Component.onCompleted: { 0027 activity.stop.connect(stop); 0028 } 0029 0030 onStop: { 0031 highlightTimer.stop(); 0032 } 0033 0034 property string noteName 0035 property string noteType 0036 property string soundPitch 0037 property string clefType 0038 property string elementType 0039 property bool noteIsColored: true 0040 property bool isDefaultClef: false 0041 property string blackType: noteName === "" ? "" 0042 : noteName[1] === "#" ? "sharp" 0043 : noteName[1] === "b" ? "flat" : ""// empty, "flat" or "sharp" 0044 0045 /** 0046 * Calculates and assign the timer interval for a note. 0047 */ 0048 function calculateTimerDuration(noteType) { 0049 noteType = noteType.toLowerCase() 0050 if(noteType === "whole") 0051 return 240000 / multipleStaff.bpmValue 0052 else if(noteType === "half") 0053 return 120000 / multipleStaff.bpmValue 0054 else if(noteType === "quarter") 0055 return 60000 / multipleStaff.bpmValue 0056 else 0057 return 30000 / multipleStaff.bpmValue 0058 } 0059 0060 readonly property int duration: { 0061 if(elementType != "clef") { 0062 if(noteType === "Rest") 0063 return calculateTimerDuration(noteName) 0064 else 0065 return calculateTimerDuration(noteType) 0066 } 0067 return 0 0068 } 0069 0070 readonly property real noteImageWidth: (multipleStaff.width - 15 - clefImageWidth) / 10 0071 0072 readonly property var noteColorMap: { "1": "#FF0000", "2": "#FF7F00", "3": "#FFFF00", 0073 "4": "#32CD32", "5": "#6495ED", "6": "#D02090", "7": "#FF1493", "8": "#FF0000", 0074 "-1": "#FF6347", "-2": "#FFD700", "-3": "#20B2AA", "-4": "#8A2BE2", 0075 "-5": "#FF00FF" } 0076 0077 readonly property var whiteNoteName: { "C": "1", "D": "2", "E": "3", "F": "4", "G": "5", "A": "6", "B": "7", "C": "8" } 0078 0079 readonly property var sharpNoteName: { "C#": "-1", "D#": "-2", "F#": "-3", "G#": "-4", "A#": "-5" } 0080 readonly property var flatNoteName: { "Db": "-1", "Eb": "-2", "Gb": "-3", "Ab": "-4", "Bb": "-5" } 0081 readonly property var blackNoteName: blackType == "" ? blackType 0082 : blackType == "flat" ? flatNoteName : sharpNoteName 0083 0084 property bool highlightWhenPlayed: false 0085 property alias highlightTimer: highlightTimer 0086 0087 property var noteDetails 0088 0089 property bool noteAnswered: false 0090 property bool isCorrectlyAnswered: false 0091 0092 rotation: { 0093 if((noteDetails === undefined) || elementType === "clef") 0094 return 0 0095 else if((noteDetails.positionOnStaff < 0) && (noteType === "Whole")) 0096 return 180 0097 else 0098 return noteDetails.rotation 0099 } 0100 0101 Image { 0102 id: blackTypeImage 0103 source: blackType !== "" ? "qrc:/gcompris/src/activities/piano_composition/resource/black" + blackType + ".svg" : "" 0104 sourceSize.width: noteImage.width / 2 0105 anchors.right: parent.rotation === 180 ? undefined : noteImage.left 0106 anchors.left: parent.rotation === 180 ? noteImage.right : undefined 0107 rotation: parent.rotation === 180 ? 180 : 0 0108 anchors.rightMargin: -noteImage.width / 4 0109 anchors.leftMargin: -noteImage.width / 2.5 0110 anchors.bottom: noteImage.bottom 0111 anchors.bottomMargin: parent.height / 6 0112 fillMode: Image.PreserveAspectFit 0113 } 0114 0115 Rectangle { 0116 id: highlightRectangle 0117 width: musicElement.width 0118 height: musicElement.height * 0.9 0119 color: "transparent" 0120 opacity: 1 0121 border.color: "#373737" 0122 border.width: radius * 0.5 0123 radius: width * 0.1 0124 visible: (multipleStaff.noteHoverEnabled && noteMouseArea.containsMouse) || highlightTimer.running 0125 } 0126 0127 Rectangle { 0128 id: selectedNoteIndicator 0129 width: musicElement.width 0130 height: musicElement.height * 0.9 0131 color: "blue" 0132 opacity: 0.6 0133 border.color: "white" 0134 radius: width / 5 0135 visible: selectedIndex == index 0136 } 0137 0138 Image { 0139 id: noteImage 0140 source: (noteDetails === undefined) ? "" 0141 : noteType != "Rest" ? "qrc:/gcompris/src/activities/piano_composition/resource/" + noteDetails.imageName + noteType + ".svg" 0142 : "qrc:/gcompris/src/activities/piano_composition/resource/" + noteDetails.imageName + ".svg" 0143 sourceSize.width: 200 0144 width: musicElement.width 0145 height: musicElement.height 0146 mirror: parent.rotation == 180 && parent.noteType == "Eighth" ? true : false 0147 } 0148 0149 Image { 0150 id: clefImage 0151 source: (elementType === "clef") ? "qrc:/gcompris/src/activities/piano_composition/resource/" + clefType.toLowerCase() + "Clef.svg" : "" 0152 sourceSize.width: multipleStaff.clefImageWidth 0153 } 0154 0155 Image { 0156 id: correctOrWrongAnswerIndicator 0157 visible: noteAnswered 0158 source: isCorrectlyAnswered ? "qrc:/gcompris/src/activities/piano_composition/resource/passed.svg" 0159 : "qrc:/gcompris/src/activities/piano_composition/resource/failed.svg" 0160 sourceSize.width: noteImage.width / 2.5 0161 anchors.right: parent.rotation === 180 ? undefined : noteImage.right 0162 anchors.left: parent.rotation === 180 ? noteImage.left : undefined 0163 rotation: parent.rotation === 180 ? 180 : 0 0164 anchors.rightMargin: 12 0165 anchors.bottom: noteImage.bottom 0166 anchors.bottomMargin: parent.height / 6 0167 fillMode: Image.PreserveAspectFit 0168 z: 3 0169 } 0170 0171 Rectangle { 0172 id:softColor 0173 readonly property int invalidConditionNumber: -6 0174 readonly property int noteColorNumber: { 0175 if(noteDetails === undefined || noteType === "" || noteType === "Rest" || noteName === "") 0176 return invalidConditionNumber 0177 else if((blackType === "") && (whiteNoteName[noteName[0]] != undefined)) 0178 return whiteNoteName[noteName[0]] 0179 else if((noteName.length > 2) && (blackNoteName[noteName.substring(0,2)] != undefined)) 0180 return blackNoteName[noteName.substring(0,2)] 0181 else 0182 return invalidConditionNumber 0183 } 0184 color: { 0185 if(multipleStaff.notesColor === "inbuilt") 0186 return (noteColorNumber > invalidConditionNumber) ? noteColorMap[noteColorNumber] : "white" 0187 else 0188 return multipleStaff.notesColor 0189 } 0190 z: -1 0191 width: noteImage.width * 0.8 0192 height: width 0193 radius: width * 0.5 0194 anchors.centerIn: noteImage 0195 opacity: softColorOpacity 0196 visible: noteIsColored && (elementType != "clef") 0197 } 0198 0199 Timer { 0200 id: highlightTimer 0201 interval: duration 0202 } 0203 }