bool DurationElement::readProperties(const QDomElement& e) { if (Element::readProperties(e)) return true; const QString& tag(e.tagName()); if (tag == "Tuplet") { // setTuplet(0); int i = e.text().toInt(); foreach(Tuplet* t, score()->tuplets) { if (t->id() == i) { setTuplet(t); if (!score()->undo()->active()) // HACK, also added in Undo::AddElement() t->add(this); break; } } if (tuplet() == 0) { qDebug("DurationElement:read(): Tuplet id %d not found", i); Tuplet* t = score()->searchTuplet(e, i); if (t) { qDebug(" ...found outside measure, input file corrupted?"); setTuplet(t); if (!score()->undo()->active()) // HACK t->add(this); score()->tuplets.append(t); } } }
double LayerElement::GetAlignmentDuration( Mensur *mensur, MeterSig *meterSig, bool notGraceOnly ) { if ( this->IsGraceNote() && notGraceOnly ) { return 0.0; } if ( this->HasInterface(INTERFACE_DURATION) ) { int num = 1; int numbase = 1; Tuplet *tuplet = dynamic_cast<Tuplet*>( this->GetFirstParent( TUPLET, MAX_TUPLET_DEPTH ) ); if ( tuplet ) { num = tuplet->GetNum(); numbase = tuplet->GetNumbase(); } DurationInterface *duration = dynamic_cast<DurationInterface*>(this); assert( duration ); if (duration->IsMensural()) return duration->GetAlignmentMensuralDuration( num, numbase, mensur ); else return duration->GetAlignmentDuration( num, numbase ); } else if (this->Is() == BEATRPT) { BeatRpt *beatRpt = dynamic_cast<BeatRpt*>(this); assert(beatRpt); int meterUnit = 4; if (meterSig) meterSig->GetUnit(); return beatRpt->GetAlignmentDuration(meterUnit); } else { return 0.0; } }
Fraction DurationElement::globalDuration() const { Fraction f(_duration); for (Tuplet* t = tuplet(); t; t = t->tuplet()) f /= t->ratio(); return f; }
void TrackList::append(Element* e) { if (e->isDurationElement()) { Fraction d = static_cast<DurationElement*>(e)->duration(); _duration += d; bool accumulateRest = e->type() == Element::REST && !isEmpty() && back()->type() == Element::REST; Segment* s = accumulateRest ? static_cast<Rest*>(e)->segment() : 0; if (s && !s->score()->isSpannerStartEnd(s->tick(), e->track())) { // akkumulate rests Rest* rest = static_cast<Rest*>(back()); Fraction d = rest->duration(); d += static_cast<Rest*>(e)->duration(); rest->setDuration(d); } else { Element* element = e->clone(); QList<Element*>::append(element); if (e->type() == Element::TUPLET) { Tuplet* srcTuplet = static_cast<Tuplet*>(e); Tuplet* dstTuplet = static_cast<Tuplet*>(element); foreach(const DurationElement* de, srcTuplet->elements()) dstTuplet->add(de->clone()); } else {
bool DurationElement::readProperties(XmlReader& e) { if (Element::readProperties(e)) return true; const QStringRef& tag(e.name()); if (tag == "Tuplet") { // setTuplet(0); int i = e.readInt(); Tuplet* t = e.findTuplet(i); if (t) { setTuplet(t); if (!score()->undo()->active()) { // HACK, also added in Undo::AddElement() t->add(this); } } else { qDebug("DurationElement:read(): Tuplet id %d not found", i); Tuplet* t = score()->searchTuplet(e, i); if (t) { qDebug(" ...found outside measure, input file corrupted?"); setTuplet(t); if (!score()->undo()->active()) // HACK t->add(this); e.addTuplet(t); } } } else return false; return true; }
void createTupletNotes( Staff *staff, const std::multimap<ReducedFraction, TupletData> &tuplets) { Score* score = staff->score(); const int track = staff->idx() * VOICES; for (const auto &tupletEvent: tuplets) { const auto &tupletData = tupletEvent.second; if (tupletData.elements.empty()) continue; Tuplet* tuplet = new Tuplet(score); const auto &tupletRatio = tupletLimits(tupletData.tupletNumber).ratio; tuplet->setRatio(tupletRatio.fraction()); tuplet->setDuration(tupletData.len.fraction()); const TDuration baseLen = tupletData.len.fraction() / tupletRatio.denominator(); tuplet->setBaseLen(baseLen); tuplet->setTrack(track); tuplet->setTick(tupletData.onTime.ticks()); tuplet->setVoice(tupletData.voice); Measure* measure = score->tick2measure(tupletData.onTime.ticks()); tuplet->setParent(measure); for (DurationElement *el: tupletData.elements) { tuplet->add(el); el->setTuplet(tuplet); } } }
void Segment::removeElement(int track) { Element* el = element(track); if (el->isChordRest()) { ChordRest* cr = (ChordRest*)el; Beam* beam = cr->beam(); if (beam) beam->remove(cr); Tuplet* tuplet = cr->tuplet(); if (tuplet) tuplet->remove(cr); } }
void MuseScore::tupletDialog() { if (!cs) return; ChordRest* cr = cs->getSelectedChordRest(); if (cr == 0) return; TupletDialog td; if (!td.exec()) return; Tuplet* tuplet = new Tuplet(cs); tuplet->setTrack(cr->track()); tuplet->setTick(cr->tick()); td.setupTuplet(tuplet); // tuplet->setRatio(tuplet->ratio().reduced()); Fraction f1(cr->duration()); tuplet->setDuration(f1); Fraction f = f1 * tuplet->ratio(); f.reduce(); printf("len %s ratio %s base %s\n", qPrintable(f1.print()), qPrintable(tuplet->ratio().print()), qPrintable(f.print())); tuplet->setBaseLen(Fraction(1, f.denominator())); Measure* measure = cr->measure(); tuplet->setParent(measure); cs->cmdCreateTuplet(cr, tuplet); }
void MTrack::createTuplets(int track, Score *score) { for (const auto &tupletEvent: tuplets) { const auto &tupletData = tupletEvent.second; if (tupletData.elements.empty()) continue; Tuplet* tuplet = new Tuplet(score); auto ratioIt = MidiTuplet::tupletRatios().find(tupletData.tupletNumber); Fraction tupletRatio = (ratioIt != MidiTuplet::tupletRatios().end()) ? ratioIt->second : Fraction(2, 2); if (ratioIt == MidiTuplet::tupletRatios().end()) qDebug("Tuplet ratio not found for tuplet number: %d", tupletData.tupletNumber); tuplet->setRatio(tupletRatio); tuplet->setDuration(tupletData.len); TDuration baseLen(tupletData.len / tupletRatio.denominator()); tuplet->setBaseLen(baseLen); tuplet->setTrack(track); tuplet->setTick(tupletData.onTime.ticks()); Measure* measure = score->tick2measure(tupletData.onTime.ticks()); tuplet->setParent(measure); for (DurationElement *el: tupletData.elements) { tuplet->add(el); el->setTuplet(tuplet); } } }
void PaeInput::addLayerElement(LayerElement *element) { if (m_nested_objects.size() > 0) { LayerElement *bottom = m_nested_objects.back(); if ( bottom->Is() == BEAM ) { Beam *beam = dynamic_cast<Beam*>( bottom ); assert( beam ); beam->AddLayerElement( element ); } else if ( bottom->Is() == TUPLET ) { Tuplet *tuplet = dynamic_cast<Tuplet*>( bottom ); assert( tuplet ); tuplet->AddLayerElement( element ); } } else { m_layer->AddLayerElement(element); } }
void SwingDetector::applySwing() { if (elements.size() != 2 && elements.size() != 3) return; Tuplet *tuplet = nullptr; for (ChordRest *el: elements) { el->setDurationType(TDuration::DurationType::V_EIGHTH); el->setTicks(Fraction(1, 8)); el->setDots(0); if (el->tuplet()) { if (!tuplet) tuplet = el->tuplet(); tuplet->remove(el); el->setTuplet(nullptr); } } const ChordRest *first = elements.front(); const int startTick = first->segment()->tick().ticks(); ChordRest *last = elements.back(); last->segment()->remove(last); Segment *s = last->measure()->getSegment(SegmentType::ChordRest, Fraction::fromTicks(startTick + MScore::division / 2)); s->add(last); if (elements.size() == 3) { // remove central rest ChordRest *cr = elements[1]; cr->score()->removeElement(cr); delete cr; } if (tuplet) { // delete tuplet delete tuplet; tuplet = nullptr; } if (!swingApplied) swingApplied = true; }
void MsScWriter::doTriplet(Chord* cr, StartStop triplet) { qDebug() << "MsScWriter::doTriplet(" << triplet << ")" ; if (triplet == ST_START) { tuplet = new Tuplet(score); tuplet->setTrack(0); tuplet->setRatio(Fraction(3, 2)); tuplet->setTick(tick); currentMeasure->add(tuplet); } else if (triplet == ST_STOP) { if (tuplet) { cr->setTuplet(tuplet); tuplet->add(cr); tuplet = 0; } else qDebug("BWW::import: triplet stop without triplet start\n"); } else if (triplet == ST_CONTINUE) { if (!tuplet) qDebug("BWW::import: triplet continue without triplet start\n"); } else if (triplet == ST_NONE) { if (tuplet) qDebug("BWW::import: triplet none inside triplet\n"); } else qDebug("unknown triplet type %d\n", triplet); if (tuplet) { cr->setTuplet(tuplet); tuplet->add(cr); } }
void PaeInput::parseNote(NoteObject note) { LayerElement *element; if (note.rest) { Rest *rest = new Rest(); rest->SetDots( note.dots ); rest->SetDur(note.duration); if (note.fermata) { rest->SetFermata(PLACE_above); // always above for now } element = rest; } else { Note *mnote = new Note(); mnote->SetPname(note.pitch); mnote->SetOct(note.octave); mnote->SetAccid(note.accidental); mnote->SetDots( note.dots ); mnote->SetDur(note.duration); if (note.fermata) { mnote->SetFermata(PLACE_above); // always above for now } if (note.trill == true) mnote->m_embellishment = EMB_TRILL; if (m_last_tied_note != NULL) { mnote->SetTie(TIE_t); m_last_tied_note = NULL; } if (note.tie) { if (mnote->GetTie()==TIE_t) mnote->SetTie(TIE_m); else mnote->SetTie(TIE_i); m_last_tied_note = mnote; } element = mnote; } // Does this note have a clef change? push it before everyting else if (note.clef) addLayerElement(note.clef); // Same thing for time changes // You can find this sometimes if (note.meter) addLayerElement(note.meter); // Handle key change. Evil if done in a beam if (note.key) addLayerElement(note.key); // Acciaccaturas are similar but do not get beamed (do they) // this case is simpler. NOTE a note can not be acciacctura AND appoggiatura // Acciaccatura rests do not exist if (note.acciaccatura && (element->Is() == NOTE) ) { Note *note = dynamic_cast<Note*>(element); assert( note ); note->SetDur(DURATION_8); note->SetGrace(GRACE_acc); note->SetStemDir(STEMDIRECTION_up); } if ( (note.appoggiatura > 0) && (element->Is() == NOTE) ) { Note *note = dynamic_cast<Note*>(element); assert( note ); note->SetGrace(GRACE_unacc); note->SetStemDir(STEMDIRECTION_up); } if (note.beam == BEAM_INITIAL) { pushContainer(new Beam()); } // we have a tuplet, the tuplet_note is > 0 // which means we are counting a tuplet if (note.tuplet_note > 0 && note.tuplet_notes == note.tuplet_note) { // first elem in tuplet Tuplet *newTuplet = new Tuplet(); newTuplet->SetNum(note.tuplet_notes); newTuplet->SetNumbase(note.tuplet_notes); pushContainer(newTuplet); } // Add the note to the current container addLayerElement(element); // the last note counts always '1' // insert the tuplet elem // and reset the tuplet counter if (note.tuplet_note == 1) popContainer(); if (note.beam == BEAM_TERMINAL) popContainer(); }
int GuitarPro5::readBeat(int tick, int voice, Measure* measure, int staffIdx, Tuplet** tuplets, bool /*mixChange*/) { uchar beatBits = readUChar(); bool dotted = beatBits & BEAT_DOTTED; slide = -1; int track = staffIdx * VOICES + voice; if (slides.contains(track)) slide = slides.take(track); int pause = -1; if (beatBits & BEAT_PAUSE) pause = readUChar(); // readDuration int len = readChar(); int tuple = 0; if (beatBits & BEAT_TUPLET) tuple = readInt(); Segment* segment = measure->getSegment(Segment::Type::ChordRest, tick); if (beatBits & BEAT_CHORD) { int numStrings = score->staff(staffIdx)->part()->instr()->stringData()->strings(); skip(17); QString name = readPascalString(21); skip(4); // no header to be read in the GP5 format - default to true. readChord(segment, staffIdx * VOICES, numStrings, name, true); skip(32); } Lyrics* lyrics = 0; if (beatBits & BEAT_LYRICS) { QString txt = readDelphiString(); lyrics = new Lyrics(score); lyrics->setText(txt); } gpLyrics.beatCounter++; if (gpLyrics.beatCounter >= gpLyrics.fromBeat && gpLyrics.lyricTrack == staffIdx+1) { int index = gpLyrics.beatCounter - gpLyrics.fromBeat; if (index < gpLyrics.lyrics.size()) { lyrics = new Lyrics(score); lyrics->setText(gpLyrics.lyrics[index]); } } int beatEffects = 0; if (beatBits & BEAT_EFFECTS) beatEffects = readBeatEffects(track, segment); if (beatBits & BEAT_MIX_CHANGE) readMixChange(measure); int strings = readUChar(); // used strings mask Fraction l = len2fraction(len); // Some beat effects could add a Chord before this ChordRest* cr = segment->cr(track); if (voice != 0 && pause == 0 && strings == 0) cr = 0; else { if (strings == 0) { if (cr) { segment->remove(cr); delete cr; cr = 0; } cr = new Rest(score); } else { if (!cr) cr = new Chord(score); } cr->setTrack(track); TDuration d(l); d.setDots(dotted ? 1 : 0); if (dotted) l = l + (l/2); if (tuple) { Tuplet* tuplet = tuplets[staffIdx * 2 + voice]; if ((tuplet == 0) || (tuplet->elementsDuration() == tuplet->baseLen().fraction() * tuplet->ratio().numerator())) { tuplet = new Tuplet(score); // int track = staffIdx * 2 + voice; tuplets[staffIdx * 2 + voice] = tuplet; tuplet->setTrack(cr->track()); setTuplet(tuplet, tuple); tuplet->setParent(measure); } tuplet->setTrack(cr->track()); tuplet->setBaseLen(l); tuplet->setDuration(l * tuplet->ratio().denominator()); cr->setTuplet(tuplet); tuplet->add(cr); } cr->setDuration(l); if (cr->type() == Element::Type::REST && (pause == 0 || l == measure->len())) cr->setDurationType(TDuration::DurationType::V_MEASURE); else cr->setDurationType(d); if(!segment->cr(track)) segment->add(cr); Staff* staff = cr->staff(); int numStrings = staff->part()->instr()->stringData()->strings(); bool hasSlur = false; for (int i = 6; i >= 0; --i) { if (strings & (1 << i) && ((6-i) < numStrings)) { Note* note = new Note(score); if (dotted) { // there is at most one dotted note in this guitar pro version NoteDot* dot = new NoteDot(score); dot->setIdx(0); dot->setParent(note); dot->setTrack(track); // needed to know the staff it belongs to (and detect tablature) dot->setVisible(true); note->add(dot); } static_cast<Chord*>(cr)->add(note); hasSlur = readNote(6-i, note); note->setTpcFromPitch(); } } createSlur(hasSlur, staffIdx, cr); if (lyrics) cr->add(lyrics); } int rr = readChar(); if (cr && (cr->type() == Element::Type::CHORD)) { Chord* chord = static_cast<Chord*>(cr); applyBeatEffects(chord, beatEffects); if (rr == ARPEGGIO_DOWN) chord->setStemDirection(MScore::Direction::DOWN); else if (rr == ARPEGGIO_UP) chord->setStemDirection(MScore::Direction::UP); } int r = readChar(); if (r & 0x8) { int rrr = readChar(); qDebug(" 3beat read 0x%02x", rrr); } if (cr && (cr->type() == Element::Type::CHORD) && slide > 0) createSlide(slide, cr, staffIdx); restsForEmptyBeats(segment, measure, cr, l, track, tick); return cr ? cr->actualTicks() : measure->ticks(); }
void MuseData::readNote(Part* part, const QString& s) { // a b c d e f g static int table[7] = { 9, 11, 0, 2, 4, 5, 7 }; int step = s[0].toLatin1() - 'A'; int alter = 0; int octave = 0; for (int i = 1; i < 3; ++i) { if (s[i] == '#') alter += 1; else if (s[i] == 'f') alter -= 1; else if (s[i].isDigit()) { octave = s.mid(i,1).toInt(); break; } } MScore::Direction dir = MScore::AUTO; if (s.size() >= 23) { if (s[22] == 'u') dir = MScore::UP; else if (s[22] == 'd') dir = MScore::DOWN; } int staffIdx = 0; if (s.size() >= 24) { if (s[23].isDigit()) staffIdx = s.mid(23,1).toInt() - 1; } Staff* staff = part->staff(staffIdx); int gstaff = staff->idx(); int pitch = table[step] + alter + (octave + 1) * 12; if (pitch < 0) pitch = 0; if (pitch > 127) pitch = 127; int ticks = s.mid(5, 3).toInt(); ticks = (ticks * MScore::division + _division/2) / _division; int tick = curTick; curTick += ticks; Tuplet* tuplet = 0; if (s.size() >= 22) { int a = 1; int b = 1; if (s[19] != ' ') { a = s[19].toLatin1() - '0'; if (a == 3 && s[20] != ':') b = 2; else { b = s[21].toLatin1() - '0'; } } if (a == 3 && b == 2) { // triplet if (chordRest && chordRest->tuplet() && ntuplet) { tuplet = chordRest->tuplet(); } else { tuplet = new Tuplet(score); tuplet->setTrack(gstaff * VOICES); tuplet->setTick(tick); ntuplet = a; tuplet->setRatio(Fraction(a, b)); measure->add(tuplet); } } else if (a == 1 && b == 1) ; else qDebug("unsupported tuple %d/%d", a, b); } Chord* chord = new Chord(score); chordRest = chord; chord->setTrack(gstaff * VOICES); chord->setStemDirection(dir); if (tuplet) { chord->setTuplet(tuplet); tuplet->add(chord); --ntuplet; } TDuration d; d.setVal(ticks); chord->setDurationType(d); Segment* segment = measure->getSegment(chord, tick); voice = 0; for (; voice < VOICES; ++voice) { Element* e = segment->element(gstaff * VOICES + voice); if (e == 0) { chord->setTrack(gstaff * VOICES + voice); segment->add(chord); break; } } if (voice == VOICES) { qDebug("cannot allocate voice"); delete chord; return; } Note* note = new Note(score); note->setPitch(pitch); note->setTpcFromPitch(); note->setTrack(gstaff * VOICES + voice); chord->add(note); QString dynamics; QString an = s.mid(31, 11); for (int i = 0; i < an.size(); ++i) { if (an[i] == '(') openSlur(0, tick, staff, voice); else if (an[i] == ')') closeSlur(0, tick, staff, voice); else if (an[i] == '[') openSlur(1, tick, staff, voice); else if (an[i] == ']') closeSlur(1, tick, staff, voice); else if (an[i] == '{') openSlur(2, tick, staff, voice); else if (an[i] == '}') closeSlur(2, tick, staff, voice); else if (an[i] == 'z') openSlur(3, tick, staff, voice); else if (an[i] == 'x') closeSlur(3, tick, staff, voice); else if (an[i] == '.') { Articulation* atr = new Articulation(score); atr->setArticulationType(Articulation_Staccato); chord->add(atr); } else if (an[i] == '_') { Articulation* atr = new Articulation(score); atr->setArticulationType(Articulation_Tenuto); chord->add(atr); } else if (an[i] == 'v') { Articulation* atr = new Articulation(score); atr->setArticulationType(Articulation_Upbow); chord->add(atr); } else if (an[i] == 'n') { Articulation* atr = new Articulation(score); atr->setArticulationType(Articulation_Downbow); chord->add(atr); } else if (an[i] == 't') { Articulation* atr = new Articulation(score); atr->setArticulationType(Articulation_Trill); chord->add(atr); } else if (an[i] == 'F') { Articulation* atr = new Articulation(score); atr->setUp(true); atr->setArticulationType(Articulation_Fermata); chord->add(atr); } else if (an[i] == 'E') { Articulation* atr = new Articulation(score); atr->setUp(false); atr->setArticulationType(Articulation_Fermata); chord->add(atr); } else if (an[i] == 'O') { // Articulation* atr = new Articulation(score); // atr->setArticulationType(Articulation_Downbow); // chord->add(atr); qDebug("%06d: open string '%c' not implemented", tick, an[i].toLatin1()); } else if (an[i] == '&') { // skip editorial level if (i <= an.size() && an[i+1].isDigit()) ++i; } else if (an[i] == 'p') dynamics += "p"; else if (an[i] == 'm') dynamics += "m"; else if (an[i] == 'f') dynamics += "f"; else if (an[i] == '-') // tie ; else if (an[i] == '*') // start tuplet ; else if (an[i] == '!') // stop tuplet ; else if (an[i] == '+') // cautionary accidental ; else if (an[i] == 'X') // ??? ; else if (an[i] == ' ') ; else { qDebug("%06d: notation '%c' not implemented", tick, an[i].toLatin1()); } } if (!dynamics.isEmpty()) { Dynamic* dyn = new Dynamic(score); dyn->setDynamicType(dynamics); dyn->setTrack(gstaff * VOICES); Segment* s = measure->getSegment(Segment::SegChordRest, tick); s->add(dyn); } QString txt = s.mid(43, 36); if (!txt.isEmpty()) { QStringList sl = txt.split("|"); int no = 0; foreach(QString w, sl) { w = diacritical(w); Lyrics* l = new Lyrics(score); l->setText(w); l->setNo(no++); l->setTrack(gstaff * VOICES); Segment* segment = measure->tick2segment(tick); segment->add(l); }
void ScoreView::elementPropertyAction(const QString& cmd, Element* e) { if (cmd == "a-props") { ArticulationProperties rp(static_cast<Articulation*>(e)); rp.exec(); } else if (cmd == "b-props") { Bend* bend = static_cast<Bend*>(e); BendProperties bp(bend, 0); if (bp.exec()) score()->undo(new ChangeBend(bend, bp.points())); } else if (cmd == "f-props") { BoxProperties vp(static_cast<Box*>(e), 0); vp.exec(); } else if (cmd == "measure-props") { MeasureProperties vp(static_cast<Note*>(e)->chord()->segment()->measure()); vp.exec(); } else if (cmd == "frame-text") { Text* s = new Text(score()); // s->setSubtype(TEXT_FRAME); s->setTextStyleType(TEXT_STYLE_FRAME); s->setParent(e); score()->undoAddElement(s); score()->select(s, SELECT_SINGLE, 0); startEdit(s); score()->setLayoutAll(true); } else if (cmd == "picture") { mscore->addImage(score(), static_cast<HBox*>(e)); } else if (cmd == "frame-text") { Text* t = new Text(score()); t->setTextStyleType(TEXT_STYLE_FRAME); t->setParent(e); score()->undoAddElement(t); score()->select(t, SELECT_SINGLE, 0); startEdit(t); } else if (cmd == "title-text") { Text* t = new Text(score()); t->setTextStyleType(TEXT_STYLE_TITLE); t->setParent(e); score()->undoAddElement(t); score()->select(t, SELECT_SINGLE, 0); startEdit(t); } else if (cmd == "subtitle-text") { Text* t = new Text(score()); t->setTextStyleType(TEXT_STYLE_SUBTITLE); t->setParent(e); score()->undoAddElement(t); score()->select(t, SELECT_SINGLE, 0); startEdit(t); } else if (cmd == "composer-text") { Text* t = new Text(score()); t->setTextStyleType(TEXT_STYLE_COMPOSER); t->setParent(e); score()->undoAddElement(t); score()->select(t, SELECT_SINGLE, 0); startEdit(t); } else if (cmd == "poet-text") { Text* t = new Text(score()); t->setTextStyleType(TEXT_STYLE_POET); t->setParent(e); score()->undoAddElement(t); score()->select(t, SELECT_SINGLE, 0); startEdit(t); } else if (cmd == "insert-hbox") { HBox* s = new HBox(score()); double w = width() - s->leftMargin() * MScore::DPMM - s->rightMargin() * MScore::DPMM; s->setBoxWidth(Spatium(w / s->spatium())); s->setParent(e); score()->undoAddElement(s); score()->select(s, SELECT_SINGLE, 0); startEdit(s); } else if (cmd == "picture") mscore->addImage(score(), e); else if (cmd == "tuplet-props") { Tuplet* tuplet; QList<Element*> el; if (e->type() == NOTE) { tuplet = static_cast<Note*>(e)->chord()->tuplet(); el.append(tuplet); } else if (e->isChordRest()) { tuplet = static_cast<ChordRest*>(e)->tuplet(); el.append(tuplet); } else { tuplet = static_cast<Tuplet*>(e); el.append(score()->selection().elements()); // apply to all selected tuplets } TupletProperties vp(tuplet); if (vp.exec()) { int bracketType = vp.bracketType(); int numberType = vp.numberType(); foreach(Element* e, el) { if (e->type() == TUPLET) { Tuplet* tuplet = static_cast<Tuplet*>(e); if (bracketType != tuplet->bracketType()) score()->undoChangeProperty(tuplet, P_BRACKET_TYPE, bracketType); if (numberType != tuplet->numberType()) score()->undoChangeProperty(tuplet, P_NUMBER_TYPE, numberType); } } }