void NoteEntryAction::mousePress(Staff* staff, int bar, const QPointF& pos) { Clef* clef = staff->lastClefChange(bar); Voice* voice = staff->part()->voice(m_tool->voice()); VoiceBar* vb = voice->bar(bar); // find element before which to insert the chord int before = 0; for (int i = 0; i < vb->elementCount(); i++) { VoiceElement* e = vb->element(i); if (e->x() >= pos.x()) break; before++; } int line = staff->line(pos.y()); int pitch = 0, accidentals = 0; if (clef && !m_isRest) { pitch = clef->lineToPitch(line); // get correct accidentals for note KeySignature* ks = staff->lastKeySignatureChange(bar); if (ks) accidentals = ks->accidentals(pitch); for (int i = 0; i < before; i++) { Chord* c = dynamic_cast<Chord*>(vb->element(i)); if (!c) continue; for (int n = 0; n < c->noteCount(); n++) { if (c->note(n)->pitch() == pitch) { accidentals = c->note(n)->accidentals(); } } } } Chord* join = NULL; if (before > 0) join = dynamic_cast<Chord*>(vb->element(before-1)); if (join && join->x() + join->width() >= pos.x()) { if (clef && !m_isRest) { m_tool->addCommand(new AddNoteCommand(m_tool->shape(), join, staff, m_duration, pitch, accidentals)); } else { m_tool->addCommand(new MakeRestCommand(m_tool->shape(), join)); } } else { if (clef && !m_isRest) { m_tool->addCommand(new CreateChordCommand(m_tool->shape(), vb, staff, m_duration, before, pitch, accidentals)); } else { m_tool->addCommand(new CreateChordCommand(m_tool->shape(), vb, staff, m_duration, before)); } } }
void testNoteAccidentals() { Sheet* sheet = new Sheet(); Bar* bar = sheet->addBar(); Part* part = sheet->addPart("part"); Voice* voice = part->addVoice(); Staff* staff = part->addStaff(); VoiceBar* vb = bar->voice(voice); for (int a = -2; a <= 2; a++) { Chord* c = new Chord(QuarterNote); c->addNote(staff, 0, a); vb->addElement(c); } validateOutput(sheet, "noteaccidentals.xml"); delete sheet; }
void testNotePitch() { Sheet* sheet = new Sheet(); Bar* bar = sheet->addBar(); Part* part = sheet->addPart("part"); Voice* voice = part->addVoice(); Staff* staff = part->addStaff(); VoiceBar* vb = bar->voice(voice); for (int p = -20; p <= 20; p++) { Chord* c = new Chord(QuarterNote); c->addNote(staff, p); vb->addElement(c); } validateOutput(sheet, "notepitch.xml"); delete sheet; }
void NoteEntryAction::renderKeyboardPreview(QPainter& painter, const MusicCursor& cursor) { Staff* staff = cursor.staff(); Part* part = staff->part(); Sheet* sheet = part->sheet(); Bar* bar = sheet->bar(cursor.bar()); QPointF p = bar->position() + QPointF(0, staff->top()); Voice* voice = cursor.staff()->part()->voice(cursor.voice()); VoiceBar* vb = voice->bar(bar); if (cursor.element() >= vb->elementCount()) { // cursor is past last element in bar, position of cursor is // halfway between last element and end of bar if (vb->elementCount() == 0) { // unless entire voicebar is still empty p.rx() += 15.0; } else { VoiceElement* ve = vb->element(vb->elementCount()-1); p.rx() += (ve->x() + bar->size()) / 2; } } else { // cursor is on an element, get the position of that element p.rx() += vb->element(cursor.element())->x(); } p.ry() += (cursor.staff()->lineCount() - 1)* cursor.staff()->lineSpacing(); p.ry() -= cursor.staff()->lineSpacing() * cursor.line() / 2; m_tool->shape()->renderer()->renderNote(painter, m_duration < QuarterNote ? QuarterNote : m_duration, p, 0, Qt::magenta); }
void testNoteDurations() { Sheet* sheet = new Sheet(); Bar* bar = sheet->addBar(); Part* part = sheet->addPart("part"); Voice* voice = part->addVoice(); Staff* staff = part->addStaff(); VoiceBar* vb = bar->voice(voice); for (Duration d = HundredTwentyEighthNote; d <= BreveNote; d = (Duration)(d + 1)) { Chord* c = new Chord(d); c->addNote(staff, 0); vb->addElement(c); } for (int i = 1; i < 4; i++) { Chord* c = new Chord(QuarterNote, i); c->addNote(staff, 0); vb->addElement(c); } validateOutput(sheet, "notedurations.xml"); delete sheet; }
void NoteEntryAction::keyPress(QKeyEvent* event, const MusicCursor& cursor) { if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { Staff* staff = cursor.staff(); //Part* part = staff->part(); //Sheet* sheet = part->sheet(); //Bar* bar = sheet->bar(cursor.bar()); Clef* clef = staff->lastClefChange(cursor.bar()); int line = cursor.line(); int pitch = 0, accidentals = 0; VoiceBar* vb = cursor.voiceBar(); if (clef) { pitch = clef->lineToPitch(line); // get correct accidentals for note KeySignature* ks = staff->lastKeySignatureChange(cursor.bar()); if (ks) accidentals = ks->accidentals(pitch); for (int i = 0; i < cursor.element(); i++) { Chord* c = dynamic_cast<Chord*>(vb->element(i)); if (!c) continue; for (int n = 0; n < c->noteCount(); n++) { if (c->note(n)->pitch() == pitch) { accidentals = c->note(n)->accidentals(); } } } } Chord* join = 0; if (cursor.element() < vb->elementCount()) join = dynamic_cast<Chord*>(vb->element(cursor.element())); if (event->modifiers() & Qt::ShiftModifier || !join) { m_tool->addCommand(new CreateChordCommand(m_tool->shape(), vb, staff, m_duration, cursor.element(), pitch, accidentals)); } else { m_tool->addCommand(new AddNoteCommand(m_tool->shape(), join, staff, join->duration(), pitch, accidentals)); } event->accept(); } }
void AbstractNoteMusicAction::mousePress(Staff* staff, int barIdx, const QPointF& pos) { Part* part = staff->part(); Sheet* sheet = part->sheet(); Bar* bar = sheet->bar(barIdx); Clef* clef = staff->lastClefChange(barIdx, 0); // loop over all noteheads qreal closestDist = 1e9; Note* closestNote = 0; Chord* chord = 0; // outer loop, loop over all voices for (int v = 0; v < part->voiceCount(); v++) { Voice* voice = part->voice(v); VoiceBar* vb = voice->bar(bar); // next loop over all chords for (int e = 0; e < vb->elementCount(); e++) { Chord* c = dynamic_cast<Chord*>(vb->element(e)); if (!c) continue; qreal centerX = c->x() + (c->width() / 2); // check if it is a rest if (c->noteCount() == 0) { qreal centerY = c->y() + (c->height() / 2); qreal dist = sqrt(sqr(centerX - pos.x()) + sqr(centerY - pos.y())); if (dist < closestDist) { closestDist = dist; closestNote = NULL; chord = c; } } // lastly loop over all noteheads for (int n = 0; n < c->noteCount(); n++) { Note* note = c->note(n); if (note->staff() != staff) continue; int line = clef->pitchToLine(note->pitch()); qreal centerY = line * staff->lineSpacing() / 2; qreal dist = sqrt(sqr(centerX - pos.x()) + sqr(centerY - pos.y())); if (dist < closestDist) { closestDist = dist; closestNote = note; chord = c; } } } } StaffElement* se = 0; for (int e = 0; e < bar->staffElementCount(staff); e++) { StaffElement* elem = bar->staffElement(staff, e); qreal centerX = elem->x() + (elem->width() / 2); qreal centerY = elem->y() + (elem->height() / 2); qreal dist = sqrt(sqr(centerX - pos.x()) + sqr(centerY - pos.y())); if (dist < closestDist) { se = elem; closestDist = dist; } } if (se) { mousePress(se, closestDist, pos); } else { mousePress(chord, closestNote, closestDist, pos); } }
static void writePart(KoXmlWriter& w, int id, Part* part) { w.startElement("music:part"); w.addAttribute("id", QString("P%1").arg(id)); for (int i = 0; i < part->sheet()->barCount(); i++) { Bar* bar = part->sheet()->bar(i); w.startElement("music:measure"); w.addAttribute("number", i+1); bool inAttributes = false; if (i == 0) { w.startElement("music:attributes"); w.startElement("music:divisions"); w.addTextNode(QString::number(QuarterLength)); w.endElement(); // music:divisions inAttributes = true; } for (int st = 0; st < part->staffCount(); st++) { Staff* staff = part->staff(st); for (int e = 0; e < bar->staffElementCount(staff); e++) { StaffElement* se = bar->staffElement(staff, e); KeySignature* ks = dynamic_cast<KeySignature*>(se); if (ks) { if (!inAttributes) { w.startElement("music:attributes"); inAttributes = true; } writeKeySignature(w, ks, part); } } } for (int st = 0; st < part->staffCount(); st++) { Staff* staff = part->staff(st); for (int e = 0; e < bar->staffElementCount(staff); e++) { StaffElement* se = bar->staffElement(staff, e); TimeSignature* ts = dynamic_cast<TimeSignature*>(se); if (ts) { if (!inAttributes) { w.startElement("music:attributes"); inAttributes = true; } writeTimeSignature(w, ts, part); } } } if (i == 0 && part->staffCount() != 1) { w.startElement("music:staves"); w.addTextNode(QString::number(part->staffCount())); w.endElement(); // music:staves } for (int st = 0; st < part->staffCount(); st++) { Staff* staff = part->staff(st); for (int e = 0; e < bar->staffElementCount(staff); e++) { StaffElement* se = bar->staffElement(staff, e); Clef* c = dynamic_cast<Clef*>(se); if (c) { if (!inAttributes) { w.startElement("music:attributes"); inAttributes = true; } writeClef(w, c, part); } } } if (inAttributes) { w.endElement(); // music:attributes } int curTime = 0; for (int voice = 0; voice < part->voiceCount(); voice++) { if (curTime != 0) { w.startElement("music:backup"); w.startElement("music:duration"); w.addTextNode(QString::number(curTime)); w.endElement(); // music:duration w.endElement(); // music:backup } Voice* v = part->voice(voice); VoiceBar* vb = part->sheet()->bar(i)->voice(v); for (int e = 0; e < vb->elementCount(); e++) { VoiceElement* ve = vb->element(e); curTime += ve->length(); Chord* c = dynamic_cast<Chord*>(ve); if(c) writeChord(w, c, v, part, i); } } w.endElement(); // music:measure } w.endElement(); // music:part }
static void writeChord(KoXmlWriter& w, Chord* chord, Voice* voice, Part* part, int bar) { if (!chord->noteCount()) { w.startElement("music:note"); w.startElement("music:rest"); w.endElement(); // music:rest w.startElement("music:duration"); w.addTextNode(QString::number(chord->length())); w.endElement(); // music:duration w.startElement("music:voice"); w.addTextNode(QString::number(part->indexOfVoice(voice) + 1)); w.endElement(); // music:voice w.startElement("music:type"); w.addTextNode(durationToString(chord->duration())); w.endElement(); // music:type for (int i = 0; i < chord->dots(); i++) { w.startElement("music:dot"); w.endElement(); // music:dot } if (part->staffCount() > 1) { // only write staff info when more than one staff exists Staff* s = chord->staff(); w.startElement("music:staff"); w.addTextNode(QString::number(part->indexOfStaff(s) + 1)); w.endElement(); //music:staff } w.endElement(); // music:note } else for (int n = 0; n < chord->noteCount(); n++) { Staff* staff = chord->note(n)->staff(); w.startElement("music:note"); if (n > 0) { w.startElement("music:chord"); w.endElement(); // music:chord } w.startElement("music:pitch"); w.startElement("music:step"); int pitch = chord->note(n)->pitch(); char note = 'A' + ((((pitch + 2) % 7) + 7) % 7); w.addTextNode(QString(note)); w.endElement(); // music:step if (chord->note(n)->accidentals()) { w.startElement("music:alter"); w.addTextNode(QString::number(chord->note(n)->accidentals())); w.endElement(); // music:alter } w.startElement("music:octave"); w.addTextNode(QString::number((pitch + 4*7) / 7)); // first add, than divide to get proper rounding w.endElement(); // music:octave w.endElement(); // music:pitch w.startElement("music:duration"); w.addTextNode(QString::number(chord->length())); w.endElement(); // music:duration w.startElement("music:voice"); w.addTextNode(QString::number(part->indexOfVoice(voice) + 1)); w.endElement(); // music:voice w.startElement("music:type"); w.addTextNode(durationToString(chord->duration())); w.endElement(); // music:type for (int i = 0; i < chord->dots(); i++) { w.startElement("music:dot"); w.endElement(); // music:dot } int activeAccidentals = 0; KeySignature* ks = staff->lastKeySignatureChange(bar); if (ks) activeAccidentals = ks->accidentals(chord->note(n)->pitch()); VoiceBar* vb = chord->voiceBar(); // next check the bar for the last previous note in the same voice with the same pitch for (int e = 0; e < vb->elementCount(); e++) { Chord* c = dynamic_cast<Chord*>(vb->element(e)); if (!c) continue; if (c == chord) break; for (int nid = 0; nid < c->noteCount(); nid++) { Note* note = c->note(nid); if (note->staff() != staff) continue; if (note->pitch() == chord->note(n)->pitch()) { activeAccidentals = note->accidentals(); } } } if (chord->note(n)->accidentals() != activeAccidentals) { w.startElement("music:accidental"); switch (chord->note(n)->accidentals()) { case -2: w.addTextNode("flat-flat"); break; case -1: w.addTextNode("flat"); break; case 0: w.addTextNode("natural"); break; case 1: w.addTextNode("sharp"); break; case 2: w.addTextNode("double-sharp"); break; } w.endElement(); // music:accidental } if (part->staffCount() > 1) { // only write staff info when more than one staff exists Staff* s = chord->note(n)->staff(); w.startElement("music:staff"); w.addTextNode(QString::number(part->indexOfStaff(s) + 1)); w.endElement(); //music:staff } w.endElement(); // music:note } }