diff --git a/src/activities/piano_composition/MultipleStaff.qml b/src/activities/piano_composition/MultipleStaff.qml
--- a/src/activities/piano_composition/MultipleStaff.qml
+++ b/src/activities/piano_composition/MultipleStaff.qml
@@ -36,12 +36,14 @@
property int nbMaxNotesPerStaff: 6
property int firstNoteX: width / 5
+ // Stores the note number and the staff number in which the replacable note is.
+ property var noteToReplace: [-1, -1]
property bool noteIsColored
property bool isMetronomeDisplayed: false
property alias flickableStaves: flickableStaves
- signal noteClicked(string noteName, string noteType)
+ signal noteClicked(string noteName, string noteType, int noteIndex, int staffIndex)
Flickable {
id: flickableStaves
@@ -85,11 +87,17 @@
currentStaff++
}
- staves.itemAt(currentStaff).addNote(noteName, noteType, highlightWhenPlayed)
+ staves.itemAt(currentStaff).addNote(noteName, noteType, highlightWhenPlayed, false)
if(playAudio)
playNoteAudio(noteName, noteType)
}
+ function replaceNote(noteName, noteType) {
+ if(noteToReplace [0] != -1 && noteToReplace[1] != -1) {
+ staves.itemAt(noteToReplace[1]).replaceNote(noteName, noteType)
+ }
+ }
+
function playNoteAudio(noteName, noteType) {
if(noteType != "Rest") {
var audioPitchType
@@ -169,6 +177,10 @@
}
}
+ function eraseNote(noteIndex, staffIndex) {
+ staves.itemAt(staffIndex).eraseNote(noteIndex)
+ }
+
function eraseAllNotes() {
for(var v = 0 ; v <= currentStaff ; ++ v)
staves.itemAt(v).eraseAllNotes()
diff --git a/src/activities/piano_composition/Note.qml b/src/activities/piano_composition/Note.qml
--- a/src/activities/piano_composition/Note.qml
+++ b/src/activities/piano_composition/Note.qml
@@ -56,6 +56,15 @@
property var noteDetails
+ rotation: {
+ if((noteDetails === undefined) || ((noteDetails.positonOnStaff < 0) && (noteType === "Whole")))
+ return 0
+ else if(noteDetails.positonOnStaff > 6 && noteType === "Whole")
+ return 180
+ else
+ return noteDetails.rotation
+ }
+
Image {
id: blackTypeImage
source: blackType !== "" ? "qrc:/gcompris/src/activities/piano_composition/resource/black" + blackType + ".svg" : ""
@@ -63,10 +72,10 @@
anchors.right: parent.rotation === 180 ? undefined : noteImage.left
anchors.left: parent.rotation === 180 ? noteImage.right : undefined
rotation: parent.rotation === 180 ? 180 : 0
- anchors.rightMargin: -width / 2
- anchors.leftMargin: -width
+ anchors.rightMargin: -12
+ anchors.leftMargin: -18
anchors.bottom: noteImage.bottom
- anchors.bottomMargin: height / 2
+ anchors.bottomMargin: parent.height / 6
fillMode: Image.PreserveAspectFit
}
@@ -92,8 +101,9 @@
Image {
id: noteImage
- source: noteType != "Rest" ? "qrc:/gcompris/src/activities/piano_composition/resource/" + noteDetails.imageName + noteType + ".svg"
- : "qrc:/gcompris/src/activities/piano_composition/resource/" + noteDetails.imageName + ".svg"
+ source: (noteDetails === undefined) ? ""
+ : noteType != "Rest" ? "qrc:/gcompris/src/activities/piano_composition/resource/" + noteDetails.imageName + noteType + ".svg"
+ : "qrc:/gcompris/src/activities/piano_composition/resource/" + noteDetails.imageName + ".svg"
sourceSize.width: 200
width: note.width
height: note.height
@@ -105,15 +115,17 @@
source: noteImage
readonly property int noteColorNumber: {
- if(noteType === "Rest")
- return 0
- else if(blackType === "")
+ if(noteDetails === undefined || noteType === "" || noteType === "Rest" || noteName === "")
+ return -6
+ else if((blackType === "") && (whiteNoteName[noteName[0]] != undefined))
return whiteNoteName[noteName[0]]
- else
+ else if((noteName.length > 2) && (blackNoteName[noteName.substring(0,2)] != undefined))
return blackNoteName[noteName.substring(0,2)]
+ else
+ return -6
}
- color: noteType != "Rest" ? noteColorMap[noteColorNumber] : "black" // make image like it lays under red glass
+ color: (noteColorNumber > -6) ? noteColorMap[noteColorNumber] : "black" // make image like it lays under red glass
visible: noteIsColored
}
diff --git a/src/activities/piano_composition/Piano_composition.qml b/src/activities/piano_composition/Piano_composition.qml
--- a/src/activities/piano_composition/Piano_composition.qml
+++ b/src/activities/piano_composition/Piano_composition.qml
@@ -108,6 +108,7 @@
property alias melodyList: melodyList
property alias file: file
property alias piano: piano
+ property alias staffModesOptions: staffModesOptions
}
onStart: { Activity.start(items) }
@@ -116,6 +117,7 @@
property string currentType: "Whole"
property string restType: "Whole"
property string clefType: bar.level == 2 ? "bass" : "treble"
+ property string staffMode: "add"
File {
id: file
@@ -171,7 +173,14 @@
anchors.top: instructionBox.bottom
anchors.topMargin: parent.height * 0.1
anchors.rightMargin: parent.width * 0.043
- onNoteClicked: playNoteAudio(noteName, noteType)
+ onNoteClicked: {
+ if(background.staffMode === "add")
+ playNoteAudio(noteName, noteType)
+ else if(background.staffMode === "replace")
+ noteToReplace = [noteIndex, staffIndex]
+ else
+ multipleStaff.eraseNote(noteIndex, staffIndex)
+ }
}
GCButtonScroll {
@@ -198,7 +207,12 @@
anchors.topMargin: horizontalLayout ? parent.height * 0.08 : parent.height * 0.025
blackLabelsVisible: [4, 5, 6, 7, 8].indexOf(items.bar.level) == -1 ? false : true
useSharpNotation: bar.level == 5 ? false : true
- onNoteClicked: multipleStaff.addNote(note, currentType, false, true)
+ onNoteClicked: {
+ if(background.staffMode === "add")
+ multipleStaff.addNote(note, currentType, false, true)
+ else if(background.staffMode === "replace")
+ multipleStaff.replaceNote(note, currentType)
+ }
}
Image {
@@ -246,10 +260,12 @@
anchors.horizontalCenter: parent.horizontalCenter
readonly property var noteLengthName: ["Whole", "Half", "Quarter", "Eighth"]
+ readonly property var staffModes: ["add", "replace", "erase"]
SwitchableOptions {
id: noteOptions
source: "qrc:/gcompris/src/activities/piano_composition/resource/genericNote%1.svg".arg(optionsRow.noteLengthName[currentIndex])
+ nbOptions: optionsRow.noteLengthName.length
onClicked: currentType = optionsRow.noteLengthName[currentIndex]
}
@@ -278,6 +294,16 @@
}
}
+ SwitchableOptions {
+ id:staffModesOptions
+ nbOptions: optionsRow.staffModes.length
+ source: "qrc:/gcompris/src/activities/piano_composition/resource/%1.svg".arg(optionsRow.staffModes[currentIndex])
+ anchors.top: parent.top
+ anchors.topMargin: 4
+ onClicked: background.staffMode = optionsRow.staffModes[currentIndex]
+ visible: true
+ }
+
Image {
id: clearButton
source: "qrc:/gcompris/src/activities/piano_composition/resource/edit-clear.svg"
@@ -337,6 +363,7 @@
readonly property string restTypeImage: ((optionsRow.noteLengthName[currentIndex] === "Half") ? "Whole" : optionsRow.noteLengthName[currentIndex]).toLowerCase()
source: "qrc:/gcompris/src/activities/piano_composition/resource/%1Rest.svg".arg(restTypeImage)
+ nbOptions: optionsRow.noteLengthName.length
onClicked: restType = optionsRow.noteLengthName[currentIndex]
rotation: optionsRow.noteLengthName[currentIndex] === "Half" ? 180 : 0
sourceSize.width: 70
@@ -354,7 +381,10 @@
onPressed: parent.scale = 0.8
onReleased: {
parent.scale = 1
- multipleStaff.addNote(restType.toLowerCase(), "Rest", false, false)
+ if(background.staffMode === "add")
+ multipleStaff.addNote(restType.toLowerCase(), "Rest", false, false)
+ else
+ multipleStaff.replaceNote(restType.toLowerCase(), "Rest")
}
}
}
diff --git a/src/activities/piano_composition/Staff.qml b/src/activities/piano_composition/Staff.qml
--- a/src/activities/piano_composition/Staff.qml
+++ b/src/activities/piano_composition/Staff.qml
@@ -51,6 +51,7 @@
property int nbMaxNotesPerStaff
property bool noteIsColored
property alias notesRepeater: notesRepeater
+ readonly property int staffNb: index
Image {
id: clefImage
@@ -136,15 +137,37 @@
return 812.5
}
- function addNote(noteName, noteType, blackType, highlightWhenPlayed) {
+ function addNote(noteName, noteType, highlightWhenPlayed, isReplacing) {
var duration
if(noteType === "Rest")
duration = calculateTimerDuration(noteName)
else
duration = calculateTimerDuration(noteType)
- notes.append({"noteName_": noteName, "noteType_": noteType, "mDuration": duration,
- "highlightWhenPlayed": highlightWhenPlayed});
+ if(!isReplacing)
+ notes.append({"noteName_": noteName, "noteType_": noteType, "mDuration": duration,
+ "highlightWhenPlayed": highlightWhenPlayed})
+ else
+ notes.set(multipleStaff.noteToReplace[0], { "noteName_": noteName, "noteType_": noteType, "mDuration": duration })
+ }
+
+ function replaceNote(newNoteName, newType) {
+ addNote(newNoteName, newType, false, true)
+ }
+
+ function eraseNote(noteIndex) {
+ var noteLength = notes.get(noteIndex).mDuration
+ var restName
+ if(noteLength === 2000)
+ restName = "whole"
+ else if(noteLength === 1500)
+ restName = "half"
+ else if(noteLength === 1000)
+ restName = "quarter"
+ else
+ restName = "eighth"
+
+ notes.set(noteIndex, { "noteName_": restName, "noteType_": "Rest" })
}
function playNote(noteId) {
@@ -172,20 +195,12 @@
height: staff.height
noteDetails: Activity.getNoteDetails(noteName, noteType)
- rotation: {
- if(noteDetails.positonOnStaff < 0 && noteType === "Whole")
- return 0
- else if(noteDetails.positonOnStaff > 6 && noteType === "Whole")
- return 180
- else
- return noteDetails.rotation
- }
MouseArea {
id: noteMouseArea
anchors.fill: parent
hoverEnabled: true
- onClicked: multipleStaff.noteClicked(noteName, noteType)
+ onClicked: multipleStaff.noteClicked(noteName, noteType, index, staff.staffNb)
}
function highlightNote() {
@@ -193,6 +208,8 @@
}
y: {
+ if(noteDetails === undefined)
+ return 0
var shift = -verticalDistanceBetweenLines / 2
var relativePosition = noteDetails.positonOnStaff
var imageY = (nbLines - 3) * verticalDistanceBetweenLines
diff --git a/src/activities/piano_composition/SwitchableOptions.qml b/src/activities/piano_composition/SwitchableOptions.qml
--- a/src/activities/piano_composition/SwitchableOptions.qml
+++ b/src/activities/piano_composition/SwitchableOptions.qml
@@ -29,6 +29,7 @@
id: switchableOptions
property int currentIndex: 0
+ property int nbOptions: 1
signal clicked
@@ -39,7 +40,7 @@
MouseArea {
anchors.fill: parent
onClicked: {
- parent.currentIndex = (parent.currentIndex + 1) % 4
+ parent.currentIndex = (parent.currentIndex + 1) % nbOptions
clickAnimation.start()
parent.clicked()
}
diff --git a/src/activities/piano_composition/piano_composition.js b/src/activities/piano_composition/piano_composition.js
--- a/src/activities/piano_composition/piano_composition.js
+++ b/src/activities/piano_composition/piano_composition.js
@@ -90,6 +90,9 @@
items.bar.level = currentLevel + 1
items.piano.currentOctaveNb = items.piano.defaultOctaveNb
items.multipleStaff.nbStaves = 2
+ items.background.staffMode = "add"
+ items.multipleStaff.noteToReplace = [-1, -1]
+ items.staffModesOptions.currentIndex = 0
}
function getNoteDetails(noteName, noteType) {
@@ -112,7 +115,7 @@
if(numberOfLevel <= ++currentLevel) {
currentLevel = 0
}
- initLevel();
+ initLevel()
}
function previousLevel() {
@@ -120,5 +123,5 @@
if(--currentLevel < 0) {
currentLevel = numberOfLevel - 1
}
- initLevel();
+ initLevel()
}
diff --git a/src/activities/piano_composition/resource/add.svg b/src/activities/piano_composition/resource/add.svg
new file mode 100644
--- /dev/null
+++ b/src/activities/piano_composition/resource/add.svg
@@ -0,0 +1,3052 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/activities/piano_composition/resource/erase.svg b/src/activities/piano_composition/resource/erase.svg
new file mode 100644
--- /dev/null
+++ b/src/activities/piano_composition/resource/erase.svg
@@ -0,0 +1,59 @@
+
+
diff --git a/src/activities/piano_composition/resource/replace.svg b/src/activities/piano_composition/resource/replace.svg
new file mode 100644
--- /dev/null
+++ b/src/activities/piano_composition/resource/replace.svg
@@ -0,0 +1,59 @@
+
+