LCOV - code coverage report
Current view: top level - src/engraving/api/v1 - elements.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 20.8 % 400 83
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "elements.h"
      24              : 
      25              : #include "engraving/dom/chord.h"
      26              : #include "engraving/dom/clef.h"
      27              : #include "engraving/dom/guitarbend.h"
      28              : #include "engraving/dom/measure.h"
      29              : #include "engraving/dom/measurenumber.h"
      30              : #include "engraving/dom/mmrestrange.h"
      31              : #include "engraving/dom/property.h"
      32              : #include "engraving/dom/score.h"
      33              : #include "engraving/dom/slur.h"
      34              : #include "engraving/dom/spacer.h"
      35              : #include "engraving/dom/system.h"
      36              : #include "engraving/dom/tremolotwochord.h"
      37              : #include "engraving/dom/trill.h"
      38              : 
      39              : #include "engraving/editing/editnote.h"
      40              : #include "engraving/editing/editsystemlocks.h"
      41              : #include "engraving/editing/transaction/transaction.h"
      42              : 
      43              : #include "engraving/style/style.h"
      44              : 
      45              : // api
      46              : #include "apistructs.h"
      47              : #include "part.h"
      48              : 
      49              : #include "log.h"
      50              : 
      51              : using namespace mu::engraving::apiv1;
      52              : 
      53              : //---------------------------------------------------------
      54              : //   EngravingItem::setOffsetX
      55              : //---------------------------------------------------------
      56              : 
      57            0 : void EngravingItem::setOffsetX(qreal offX)
      58              : {
      59            0 :     const qreal offY = element()->offset().y() / element()->spatium();
      60            0 :     set(mu::engraving::Pid::OFFSET, QPointF(offX, offY));
      61            0 : }
      62              : 
      63              : //---------------------------------------------------------
      64              : //   EngravingItem::setOffsetY
      65              : //---------------------------------------------------------
      66              : 
      67            0 : void EngravingItem::setOffsetY(qreal offY)
      68              : {
      69            0 :     const qreal offX = element()->offset().x() / element()->spatium();
      70            0 :     set(mu::engraving::Pid::OFFSET, QPointF(offX, offY));
      71            0 : }
      72              : 
      73              : //---------------------------------------------------------
      74              : //   Number positions of multimeasure rests
      75              : //---------------------------------------------------------
      76              : 
      77            0 : QVariant EngravingItem::mmRestNumberPos() const
      78              : {
      79            0 :     if (!element()->isMMRest()) {
      80            0 :         return QVariant();
      81              :     }
      82            0 :     return element()->style().styleS(Sid::mmRestNumberPos).val() + get(Pid::MMREST_NUMBER_OFFSET).toDouble();
      83              : }
      84              : 
      85            0 : void EngravingItem::setMmRestNumberPos(const QVariant& pos)
      86              : {
      87            0 :     if (!element()->isMMRest()) {
      88            0 :         return;
      89              :     }
      90            0 :     set(Pid::MMREST_NUMBER_OFFSET, pos.toDouble() - element()->style().styleS(Sid::mmRestNumberPos).val());
      91              : }
      92              : 
      93            0 : void EngravingItem::resetMmRestNumberPos()
      94              : {
      95            0 :     reset(Pid::MMREST_NUMBER_OFFSET);
      96            0 : }
      97              : 
      98              : //---------------------------------------------------------
      99              : //   Number positions of measure repeats
     100              : //---------------------------------------------------------
     101              : 
     102            0 : QVariant EngravingItem::measureRepeatNumberPos() const
     103              : {
     104            0 :     if (!element()->isMeasureRepeat()) {
     105            0 :         return QVariant();
     106              :     }
     107            0 :     return element()->style().styleS(Sid::measureRepeatNumberPos).val() + get(Pid::MEASURE_REPEAT_NUMBER_OFFSET).toDouble();
     108              : }
     109              : 
     110            0 : void EngravingItem::setMeasureRepeatNumberPos(const QVariant& pos)
     111              : {
     112            0 :     if (!element()->isMeasureRepeat()) {
     113            0 :         return;
     114              :     }
     115            0 :     set(Pid::MEASURE_REPEAT_NUMBER_OFFSET, pos.toDouble() - element()->style().styleS(Sid::measureRepeatNumberPos).val());
     116              : }
     117              : 
     118            0 : void EngravingItem::resetMeasureRepeatNumberPos()
     119              : {
     120            0 :     reset(Pid::MEASURE_REPEAT_NUMBER_OFFSET);
     121            0 : }
     122              : 
     123            0 : static QRectF scaleRect(const mu::engraving::RectF& rect, double spatium)
     124              : {
     125            0 :     return QRectF(rect.x() / spatium, rect.y() / spatium, rect.width() / spatium, rect.height() / spatium);
     126              : }
     127              : 
     128              : //---------------------------------------------------------
     129              : //   EngravingItem::bbox
     130              : //   return the element bbox in spatium units, rather than in raster units as stored internally
     131              : //---------------------------------------------------------
     132              : 
     133            0 : QRectF EngravingItem::bbox() const
     134              : {
     135            0 :     return scaleRect(element()->ldata()->bbox(), element()->spatium());
     136              : }
     137              : 
     138            0 : bool EngravingItem::isHeader() const
     139              : {
     140            0 :     return element()->isClef() && toClef(element())->isHeader();
     141              : }
     142              : 
     143            0 : bool EngravingItem::up() const
     144              : {
     145            0 :     if (element()->isChordRest()) {
     146            0 :         return toChordRest(element())->ldata()->up;
     147            0 :     } else if (element()->isStem()) {
     148            0 :         return toStem(element())->up();
     149            0 :     } else if (element()->isSlur()) {
     150            0 :         return toSlur(element())->up();
     151            0 :     } else if (element()->isTie()) {
     152            0 :         return toTie(element())->up();
     153            0 :     } else if (element()->isSlurTieSegment()) {
     154            0 :         return toSlurTieSegment(element())->slurTie()->up();
     155            0 :     } else if (element()->isArticulation()) {
     156            0 :         return toArticulation(element())->ldata()->up;
     157            0 :     } else if (element()->isGuitarBend()) {
     158            0 :         return toGuitarBend(element())->ldata()->up();
     159            0 :     } else if (element()->isGuitarBendSegment()) {
     160            0 :         return toGuitarBendSegment(element())->guitarBend()->ldata()->up();
     161            0 :     } else if (element()->isBeam()) {
     162            0 :         return toBeam(element())->up();
     163            0 :     } else if (element()->isTuplet()) {
     164            0 :         return toTuplet(element())->isUp();
     165            0 :     } else if (element()->type() == mu::engraving::ElementType::TREMOLO_TWOCHORD) {
     166            0 :         return item_cast<const TremoloTwoChord*>(element())->up();
     167              :     }
     168            0 :     return false;
     169              : }
     170              : 
     171            0 : Fraction* EngravingItem::tick() const
     172              : {
     173            0 :     return wrap(element()->tick());
     174              : }
     175              : 
     176            0 : Fraction* EngravingItem::beat() const
     177              : {
     178            0 :     return wrap(element()->beat());
     179              : }
     180              : 
     181              : //---------------------------------------------------------
     182              : //   ChordRest::actualBeamMode
     183              : //---------------------------------------------------------
     184              : 
     185            0 : int ChordRest::actualBeamMode(bool beamRests)
     186              : {
     187            0 :     if (chordRest()->isRest() && !beamRests && chordRest()->beamMode() == mu::engraving::BeamMode::AUTO) {
     188            0 :         return int(mu::engraving::BeamMode::NONE);
     189              :     }
     190            0 :     mu::engraving::ChordRest* prev = nullptr;
     191            0 :     if (!(chordRest()->isChord() && toChord(chordRest())->isGrace())) {
     192            0 :         mu::engraving::Segment* seg = chordRest()->segment();
     193            0 :         mu::engraving::Measure* m = seg->measure();
     194            0 :         while (seg && seg->measure()->system() == m->system()) {
     195            0 :             seg = seg->prev1(mu::engraving::SegmentType::ChordRest);
     196            0 :             if (seg && seg->element(chordRest()->track())) {
     197            0 :                 prev = toChordRest(seg->element(chordRest()->track()));
     198            0 :                 break;
     199              :             }
     200              :         }
     201              :     }
     202            0 :     return int(mu::engraving::Groups::actualBeamMode(chordRest(), prev));
     203              : }
     204              : 
     205              : //---------------------------------------------------------
     206              : //   Segment::elementAt
     207              : //---------------------------------------------------------
     208              : 
     209            0 : EngravingItem* Segment::elementAt(int track)
     210              : {
     211            0 :     mu::engraving::EngravingItem* el = segment()->element(track);
     212            0 :     if (!el) {
     213            0 :         return nullptr;
     214              :     }
     215            0 :     return wrap(el, Ownership::SCORE);
     216              : }
     217              : 
     218            0 : Fraction* Segment::fraction() const
     219              : {
     220            0 :     return wrap(segment()->tick());
     221              : }
     222              : 
     223              : //---------------------------------------------------------
     224              : //   Note::setTpc
     225              : //---------------------------------------------------------
     226              : 
     227            0 : void Note::setTpc(int val)
     228              : {
     229            0 :     if (!tpcIsValid(val)) {
     230            0 :         LOGW("PluginAPI::Note::setTpc: invalid tpc: %d", val);
     231            0 :         return;
     232              :     }
     233              : 
     234            0 :     if (note()->concertPitch()) {
     235            0 :         set(Pid::TPC1, val);
     236              :     } else {
     237            0 :         set(Pid::TPC2, val);
     238              :     }
     239              : }
     240              : 
     241              : //---------------------------------------------------------
     242              : //   Note::isChildAllowed
     243              : ///   Check if element type can be a child of note.
     244              : ///   \since MuseScore 3.3.3
     245              : //---------------------------------------------------------
     246              : 
     247            0 : bool Note::isChildAllowed(mu::engraving::ElementType elementType)
     248              : {
     249            0 :     switch (elementType) {
     250            0 :     case ElementType::NOTEHEAD:
     251              :     case ElementType::NOTEDOT:
     252              :     case ElementType::FINGERING:
     253              :     case ElementType::SYMBOL:
     254              :     case ElementType::IMAGE:
     255              :     case ElementType::TEXT:
     256              :     case ElementType::BEND:
     257              :     case ElementType::TIE:
     258              :     case ElementType::PARTIAL_TIE:
     259              :     case ElementType::LAISSEZ_VIB:
     260              :     case ElementType::ACCIDENTAL:
     261              :     case ElementType::TEXTLINE:
     262              :     case ElementType::NOTELINE:
     263              :     case ElementType::GLISSANDO:
     264              :     case ElementType::HAMMER_ON_PULL_OFF:
     265            0 :         return true;
     266            0 :     default:
     267            0 :         return false;
     268              :     }
     269              : }
     270              : 
     271              : //---------------------------------------------------------
     272              : //   Note::add
     273              : ///   \since MuseScore 3.3.3
     274              : //---------------------------------------------------------
     275              : 
     276            0 : void Note::add(apiv1::EngravingItem* wrapped)
     277              : {
     278            0 :     mu::engraving::EngravingItem* s = wrapped ? wrapped->element() : nullptr;
     279            0 :     if (s) {
     280              :         // Ensure that the object has the expected ownership
     281            0 :         if (wrapped->ownership() == Ownership::SCORE) {
     282            0 :             LOGW("Note::add: Cannot add this element. The element is already part of the score.");
     283            0 :             return;              // Don't allow operation.
     284              :         }
     285              :         // Score now owns the object.
     286            0 :         wrapped->setOwnership(Ownership::SCORE);
     287              : 
     288            0 :         addInternal(note(), s);
     289              :     }
     290              : }
     291              : 
     292              : //---------------------------------------------------------
     293              : //   Note::addInternal
     294              : ///   \since MuseScore 3.3.3
     295              : //---------------------------------------------------------
     296              : 
     297            0 : void Note::addInternal(mu::engraving::Note* note, mu::engraving::EngravingItem* s)
     298              : {
     299              :     // Provide parentage for element.
     300            0 :     s->setScore(note->score());
     301            0 :     s->setOwnershipParent(note);
     302            0 :     s->setTrack(note->track());
     303              : 
     304            0 :     if (s && isChildAllowed(s->type())) {
     305              :         // Create undo op and add the element.
     306            0 :         toScore(note->score())->undoAddElement(s);
     307            0 :     } else if (s) {
     308            0 :         LOGD("Note::add() not impl. %s", s->typeName());
     309              :     }
     310            0 : }
     311              : 
     312              : //---------------------------------------------------------
     313              : //   Note::remove
     314              : ///   \since MuseScore 3.3.3
     315              : //---------------------------------------------------------
     316              : 
     317            0 : void Note::remove(apiv1::EngravingItem* wrapped)
     318              : {
     319            0 :     mu::engraving::EngravingItem* s = wrapped->element();
     320            0 :     if (!s) {
     321            0 :         LOGW("PluginAPI::Note::remove: Unable to retrieve element. %s", qPrintable(wrapped->name()));
     322            0 :     } else if (s->ownershipParent() != note()) {
     323            0 :         LOGW("PluginAPI::Note::remove: The element is not a child of this note. Use removeElement() instead.");
     324            0 :     } else if (isChildAllowed(s->type())) {
     325            0 :         note()->score()->deleteItem(s);     // Create undo op and remove the element.
     326              :     } else {
     327            0 :         LOGD("Note::remove() not impl. %s", s->typeName());
     328              :     }
     329            0 : }
     330              : 
     331              : //---------------------------------------------------------
     332              : //   DurationElement::ticks
     333              : //---------------------------------------------------------
     334              : 
     335            0 : Fraction* DurationElement::ticks() const
     336              : {
     337            0 :     return wrap(durationElement()->ticks());
     338              : }
     339              : 
     340              : //---------------------------------------------------------
     341              : //   DurationElement::changeCRlen
     342              : //---------------------------------------------------------
     343              : 
     344            0 : void DurationElement::changeCRlen(Fraction* len)
     345              : {
     346            0 :     if (!durationElement()->isChordRest()) {
     347            0 :         LOGW("DurationElement::changeCRlen: can only change length for chords or rests");
     348            0 :         return;
     349              :     }
     350            0 :     const mu::engraving::Fraction f = len->fraction();
     351            0 :     if (!f.isValid() || f.isZero() || f.negative()) {
     352            0 :         LOGW("DurationElement::changeCRlen: invalid parameter values: %s", qPrintable(f.toString()));
     353            0 :         return;
     354              :     }
     355            0 :     if (durationElement()->isChord() && toChord(durationElement())->isGrace()) {
     356            0 :         durationElement()->score()->undoChangeChordRestLen(toChord(durationElement()), f);
     357              :     } else {
     358            0 :         durationElement()->score()->changeCRlen(toChordRest(durationElement()), f);
     359              :     }
     360              : }
     361              : 
     362              : //---------------------------------------------------------
     363              : //   DurationElement::globalDuration
     364              : //---------------------------------------------------------
     365              : 
     366            0 : Fraction* DurationElement::globalDuration() const
     367              : {
     368            0 :     return wrap(durationElement()->globalTicks());
     369              : }
     370              : 
     371              : //---------------------------------------------------------
     372              : //   DurationElement::actualDuration
     373              : //---------------------------------------------------------
     374              : 
     375            0 : Fraction* DurationElement::actualDuration() const
     376              : {
     377            0 :     return wrap(durationElement()->actualTicks());
     378              : }
     379              : 
     380              : //---------------------------------------------------------
     381              : //   DurationElement::parentTuplet
     382              : //---------------------------------------------------------
     383              : 
     384            0 : Tuplet* DurationElement::parentTuplet()
     385              : {
     386            0 :     return wrap<Tuplet>(durationElement()->tuplet());
     387              : }
     388              : 
     389              : //---------------------------------------------------------
     390              : //   Chord::setPlayEventType
     391              : //---------------------------------------------------------
     392              : 
     393            0 : void Chord::setPlayEventType(mu::engraving::PlayEventType v)
     394              : {
     395              :     // Only create undo operation if the value has changed.
     396            0 :     if (v != chord()->playEventType()) {
     397            0 :         chord()->score()->undo(new ChangeChordPlayEventType(chord(), v));
     398              :     }
     399            0 : }
     400              : 
     401              : //---------------------------------------------------------
     402              : //   Chord::add
     403              : //---------------------------------------------------------
     404              : 
     405            0 : void Chord::add(apiv1::EngravingItem* wrapped)
     406              : {
     407            0 :     mu::engraving::EngravingItem* s = wrapped ? wrapped->element() : nullptr;
     408            0 :     if (s) {
     409              :         // Ensure that the object has the expected ownership
     410            0 :         if (wrapped->ownership() == Ownership::SCORE) {
     411            0 :             LOGW("Chord::add: Cannot add this element. The element is already part of the score.");
     412            0 :             return;              // Don't allow operation.
     413              :         }
     414              :         // Score now owns the object.
     415            0 :         wrapped->setOwnership(Ownership::SCORE);
     416              : 
     417            0 :         addInternal(chord(), s);
     418              :     }
     419              : }
     420              : 
     421              : //---------------------------------------------------------
     422              : //   Chord::addInternal
     423              : //---------------------------------------------------------
     424              : 
     425            0 : void Chord::addInternal(mu::engraving::Chord* chord, mu::engraving::EngravingItem* s)
     426              : {
     427              :     // Provide parentage for element.
     428            0 :     s->setScore(chord->score());
     429            0 :     s->setOwnershipParent(chord);
     430              :     // If a note, ensure the element has proper Tpc values. (Will crash otherwise)
     431            0 :     if (s->isNote()) {
     432            0 :         s->setTrack(chord->track());
     433            0 :         toNote(s)->setTpcFromPitch();
     434              :     }
     435              :     // Create undo op and add the element.
     436            0 :     chord->score()->undoAddElement(s);
     437            0 : }
     438              : 
     439              : //---------------------------------------------------------
     440              : //   Chord::remove
     441              : //---------------------------------------------------------
     442              : 
     443            0 : void Chord::remove(apiv1::EngravingItem* wrapped)
     444              : {
     445            0 :     mu::engraving::EngravingItem* s = wrapped->element();
     446            0 :     if (!s) {
     447            0 :         LOGW("PluginAPI::Chord::remove: Unable to retrieve element. %s", qPrintable(wrapped->name()));
     448            0 :     } else if (s->ownershipParent() != chord()) {
     449            0 :         LOGW("PluginAPI::Chord::remove: The element is not a child of this chord. Use removeElement() instead.");
     450            0 :     } else if (chord()->notes().size() <= 1 && s->isNote()) {
     451            0 :         LOGW("PluginAPI::Chord::remove: Removal of final note is not allowed.");
     452              :     } else {
     453            0 :         chord()->score()->deleteItem(s);     // Create undo op and remove the element.
     454              :     }
     455            0 : }
     456              : 
     457            0 : EngravingItem* Measure::vspacerUp(int staffIdx)
     458              : {
     459            0 :     return wrap(measure()->vspacerUp(static_cast<staff_idx_t>(staffIdx)));
     460              : }
     461              : 
     462            0 : EngravingItem* Measure::vspacerDown(int staffIdx)
     463              : {
     464            0 :     return wrap(measure()->vspacerDown(static_cast<staff_idx_t>(staffIdx)));
     465              : }
     466              : 
     467            0 : EngravingItem* Measure::measureNumber(int staffIdx)
     468              : {
     469            0 :     return wrap(measure()->measureNumber(static_cast<staff_idx_t>(staffIdx)));
     470              : }
     471              : 
     472            0 : EngravingItem* Measure::mmRangeText(int staffIdx)
     473              : {
     474            0 :     return wrap(measure()->mmRangeText(static_cast<staff_idx_t>(staffIdx)));
     475              : }
     476              : 
     477            0 : bool Measure::corrupted(int staffIdx)
     478              : {
     479            0 :     return measure()->corrupted(static_cast<staff_idx_t>(staffIdx));
     480              : }
     481              : 
     482            0 : bool Measure::visible(int staffIdx)
     483              : {
     484            0 :     return measure()->visible(static_cast<staff_idx_t>(staffIdx));
     485              : }
     486              : 
     487            0 : bool Measure::stemless(int staffIdx)
     488              : {
     489            0 :     return measure()->stemless(static_cast<staff_idx_t>(staffIdx));
     490              : }
     491              : 
     492            0 : Fraction* MeasureBase::tick() const
     493              : {
     494            0 :     return wrap(measureBase()->tick());
     495              : }
     496              : 
     497            0 : Fraction* MeasureBase::ticks() const
     498              : {
     499            0 :     return wrap(measureBase()->ticks());
     500              : }
     501              : 
     502            0 : void MeasureBase::add(apiv1::EngravingItem* wrapped)
     503              : {
     504            0 :     mu::engraving::EngravingItem* s = wrapped ? wrapped->element() : nullptr;
     505            0 :     if (s) {
     506              :         // Ensure that the object has the expected ownership
     507            0 :         if (wrapped->ownership() == Ownership::SCORE) {
     508            0 :             LOGW("MeasureBase::add: Cannot add this element. The element is already part of the score.");
     509            0 :             return;              // Don't allow operation.
     510              :         }
     511              :         // Score now owns the object.
     512            0 :         wrapped->setOwnership(Ownership::SCORE);
     513              : 
     514            0 :         addInternal(measureBase(), s);
     515              :     }
     516              : }
     517              : 
     518            0 : void MeasureBase::addInternal(mu::engraving::MeasureBase* measureBase, mu::engraving::EngravingItem* s)
     519              : {
     520            0 :     s->setScore(measureBase->score());
     521            0 :     s->setOwnershipParent(measureBase);
     522            0 :     measureBase->score()->undoAddElement(s);
     523            0 : }
     524              : 
     525            0 : void MeasureBase::remove(apiv1::EngravingItem* wrapped)
     526              : {
     527            0 :     mu::engraving::EngravingItem* s = wrapped->element();
     528            0 :     if (!s) {
     529            0 :         LOGW("PluginAPI::MeasureBase::remove: Unable to retrieve element. %s", qPrintable(wrapped->name()));
     530            0 :     } else if (s->ownershipParent() != measureBase()) {
     531            0 :         LOGW("PluginAPI::MeasureBase::remove: The element is not a child of this measure base. Use removeElement() instead.");
     532              :     } else {
     533            0 :         measureBase()->score()->deleteItem(s);     // Create undo op and remove the element.
     534              :     }
     535            0 : }
     536              : 
     537            0 : QRectF System::bbox(int staffIdx)
     538              : {
     539            0 :     mu::engraving::SysStaff* ss = muse::value(system()->staves(), static_cast<staff_idx_t>(staffIdx));
     540            0 :     return ss ? scaleRect(ss->bbox(), system()->spatium()) : QRectF();
     541              : }
     542              : 
     543            0 : qreal System::yOffset(int staffIdx)
     544              : {
     545            0 :     mu::engraving::SysStaff* ss = muse::value(system()->staves(), static_cast<staff_idx_t>(staffIdx));
     546            0 :     return ss ? ss->yOffset() / system()->spatium() : 0.0;
     547              : }
     548              : 
     549            0 : bool System::show(int staffIdx)
     550              : {
     551            0 :     mu::engraving::SysStaff* ss = muse::value(system()->staves(), static_cast<staff_idx_t>(staffIdx));
     552            0 :     return ss ? ss->show() : false;
     553              : }
     554              : 
     555            0 : void System::setHideStaffIfEmpty(int staffIdx, int hide)
     556              : {
     557            0 :     system()->score()->cmdSetHideStaffIfEmptyOverride(static_cast<staff_idx_t>(staffIdx), system(), AutoOnOff(hide));
     558            0 : }
     559              : 
     560            0 : void System::setIsLocked(bool locked)
     561              : {
     562            0 :     if (locked == isLocked()) {
     563            0 :         return;
     564              :     }
     565            0 :     Transaction& tx = system()->score()->transactionManager()->currentOrDummyTransaction();
     566            0 :     const mu::engraving::RangeLock* currentLock = system()->systemLock();
     567            0 :     if (currentLock && !locked) {
     568            0 :         EditSystemLocks::undoRemoveSystemLock(tx, currentLock);
     569            0 :     } else if (!currentLock && locked) {
     570            0 :         EditSystemLocks::undoAddSystemLock(tx, new mu::engraving::RangeLock(system()->first(), system()->last()));
     571              :     }
     572              : }
     573              : 
     574              : //---------------------------------------------------------
     575              : //   Page::pageNumber
     576              : //---------------------------------------------------------
     577              : 
     578            0 : int Page::pageNumber() const
     579              : {
     580            0 :     return static_cast<int>(page()->pageNumber());
     581              : }
     582              : 
     583              : //---------------------------------------------------------
     584              : //   Staff::part
     585              : //---------------------------------------------------------
     586              : 
     587            0 : Part* Staff::part()
     588              : {
     589            0 :     return wrap<Part>(staff()->part());
     590              : }
     591              : 
     592            0 : int Staff::clefType(Fraction* tick)
     593              : {
     594            0 :     return int(staff()->clef(tick->fraction()));
     595              : }
     596              : 
     597            0 : Fraction* Staff::timeStretch(Fraction* tick)
     598              : {
     599            0 :     return wrap(staff()->timeStretch(tick->fraction()));
     600              : }
     601              : 
     602            0 : EngravingItem* Staff::timeSig(Fraction* tick)
     603              : {
     604            0 :     return wrap(staff()->timeSig(tick->fraction()));
     605              : }
     606              : 
     607            0 : int Staff::key(Fraction* tick)
     608              : {
     609            0 :     return int(staff()->key(tick->fraction()));
     610              : }
     611              : 
     612            0 : IntervalWrapper* Staff::transpose(Fraction* tick)
     613              : {
     614            0 :     return wrap(staff()->transpose(tick->fraction()));
     615              : }
     616              : 
     617            0 : QVariantMap Staff::swing(Fraction* f)
     618              : {
     619            0 :     mu::engraving::SwingParameters swingParams = staff()->swing(f->fraction());
     620            0 :     QVariantMap pluginSwingParams;
     621            0 :     pluginSwingParams["swingUnit"] = swingParams.swingUnit;
     622            0 :     pluginSwingParams["swingRatio"] = swingParams.swingRatio;
     623            0 :     pluginSwingParams["isOn"] = swingParams.isOn();
     624            0 :     return pluginSwingParams;
     625            0 : }
     626              : 
     627            0 : QVariantMap Staff::capo(Fraction* f)
     628              : {
     629            0 :     const mu::engraving::CapoParams& capoParams = staff()->capo(f->fraction());
     630            0 :     QVariantMap pluginCapoParams;
     631            0 :     pluginCapoParams["active"] = capoParams.active;
     632            0 :     pluginCapoParams["fretPosition"] = capoParams.fretPosition;
     633            0 :     QVariantList ignoredStrings;
     634            0 :     ignoredStrings.reserve(static_cast<int>(capoParams.ignoredStrings.size()));
     635            0 :     for (size_t string : capoParams.ignoredStrings) {
     636            0 :         ignoredStrings.append(static_cast<int>(string));
     637              :     }
     638            0 :     pluginCapoParams["ignoredStrings"] = ignoredStrings;
     639            0 :     return pluginCapoParams;
     640            0 : }
     641              : 
     642            0 : bool Staff::stemless(Fraction* tick)
     643              : {
     644            0 :     return staff()->stemless(tick->fraction());
     645              : }
     646              : 
     647            0 : qreal Staff::staffHeight(Fraction* tick)
     648              : {
     649            0 :     return staff()->staffHeight(tick->fraction());
     650              : }
     651              : 
     652            0 : bool Staff::isPitchedStaff(Fraction* tick)
     653              : {
     654            0 :     return staff()->isPitchedStaff(tick->fraction());
     655              : }
     656              : 
     657            0 : bool Staff::isTabStaff(Fraction* tick)
     658              : {
     659            0 :     return staff()->isTabStaff(tick->fraction());
     660              : }
     661              : 
     662            0 : bool Staff::isDrumStaff(Fraction* tick)
     663              : {
     664            0 :     return staff()->isDrumStaff(tick->fraction());
     665              : }
     666              : 
     667            0 : int Staff::lines(Fraction* tick)
     668              : {
     669            0 :     return staff()->lines(tick->fraction());
     670              : }
     671              : 
     672            0 : qreal Staff::lineDistance(Fraction* tick)
     673              : {
     674            0 :     return staff()->lineDistance(tick->fraction());
     675              : }
     676              : 
     677            0 : bool Staff::isLinesInvisible(Fraction* tick)
     678              : {
     679            0 :     return staff()->isLinesInvisible(tick->fraction());
     680              : }
     681              : 
     682            0 : int Staff::middleLine(Fraction* tick)
     683              : {
     684            0 :     return staff()->middleLine(tick->fraction());
     685              : }
     686              : 
     687            0 : int Staff::bottomLine(Fraction* tick)
     688              : {
     689            0 :     return staff()->bottomLine(tick->fraction());
     690              : }
     691              : 
     692            0 : qreal Staff::staffMag(Fraction* tick)
     693              : {
     694            0 :     return staff()->staffMag(tick->fraction());
     695              : }
     696              : 
     697            0 : qreal Staff::spatium(Fraction* tick)
     698              : {
     699            0 :     return staff()->spatium(tick->fraction());
     700              : }
     701              : 
     702            0 : int Staff::pitchOffset(Fraction* tick)
     703              : {
     704            0 :     return staff()->pitchOffset(tick->fraction());
     705              : }
     706              : 
     707            0 : bool Staff::isVoiceVisible(int voice)
     708              : {
     709            0 :     return staff()->isVoiceVisible(voice);
     710              : }
     711              : 
     712              : //---------------------------------------------------------
     713              : //   Spanner::ornament
     714              : //---------------------------------------------------------
     715              : 
     716            0 : Ornament* Spanner::ornament() const
     717              : {
     718            0 :     if (spanner()->isTrill()) {
     719            0 :         return wrap<Ornament>(toTrill(spanner())->ornament());
     720              :     }
     721            0 :     return nullptr;
     722              : }
     723              : 
     724              : //---------------------------------------------------------
     725              : //   FretDiagram::setDot
     726              : //   FretDiagram::setMarker
     727              : //   FretDiagram::setBarre
     728              : //   FretDiagram::clear
     729              : ///   When the element is owned by the score, use the undo-aware DOM methods
     730              : ///   so that modifications are recorded on the undo stack and propagated to
     731              : ///   all linked clones. When the element is plugin-owned (not yet added to
     732              : ///   a score), use the direct setters to avoid accessing an invalid undo
     733              : ///   stack (see ScoreElement::set() in scoreelement.cpp for the same pattern).
     734              : //---------------------------------------------------------
     735              : 
     736            4 : void FretDiagram::setDot(int string, int fret, bool add, int dotType)
     737              : {
     738            4 :     if (string < 0 || string >= fretDiagram()->strings()) {
     739            1 :         LOGW("PluginAPI::FretDiagram::setDot: string %d is out of range (0..%d)", string, fretDiagram()->strings() - 1);
     740            1 :         return;
     741              :     }
     742            3 :     if (fret < 0) {
     743            1 :         LOGW("PluginAPI::FretDiagram::setDot: fret %d is negative", fret);
     744            1 :         return;
     745              :     }
     746            2 :     if (dotType < int(mu::engraving::FretDotType::NORMAL)
     747            2 :         || dotType > int(mu::engraving::FretDotType::TRIANGLE)) {
     748            1 :         LOGW("PluginAPI::FretDiagram::setDot: dotType %d is out of range", dotType);
     749            1 :         return;
     750              :     }
     751            1 :     if (ownership() == Ownership::SCORE) {
     752            1 :         fretDiagram()->undoSetFretDot(string, fret, add,
     753              :                                       static_cast<mu::engraving::FretDotType>(dotType));
     754              :     } else {
     755            0 :         fretDiagram()->setDot(string, fret, add,
     756              :                               static_cast<mu::engraving::FretDotType>(dotType));
     757              :     }
     758              : }
     759              : 
     760            3 : void FretDiagram::setMarker(int string, int marker)
     761              : {
     762            3 :     if (string < 0 || string >= fretDiagram()->strings()) {
     763            1 :         LOGW("PluginAPI::FretDiagram::setMarker: string %d is out of range (0..%d)", string, fretDiagram()->strings() - 1);
     764            1 :         return;
     765              :     }
     766            2 :     if (marker < int(mu::engraving::FretMarkerType::NONE)
     767            2 :         || marker > int(mu::engraving::FretMarkerType::CROSS)) {
     768            1 :         LOGW("PluginAPI::FretDiagram::setMarker: marker %d is out of range", marker);
     769            1 :         return;
     770              :     }
     771            1 :     if (ownership() == Ownership::SCORE) {
     772            1 :         fretDiagram()->undoSetFretMarker(string,
     773              :                                          static_cast<mu::engraving::FretMarkerType>(marker));
     774              :     } else {
     775            0 :         fretDiagram()->setMarker(string,
     776              :                                  static_cast<mu::engraving::FretMarkerType>(marker));
     777              :     }
     778              : }
     779              : 
     780            3 : void FretDiagram::setBarre(int string, int fret, bool add)
     781              : {
     782            3 :     if (string < 0 || string >= fretDiagram()->strings()) {
     783            1 :         LOGW("PluginAPI::FretDiagram::setBarre: string %d is out of range (0..%d)", string, fretDiagram()->strings() - 1);
     784            1 :         return;
     785              :     }
     786            2 :     if (fret <= 0) {
     787            1 :         LOGW("PluginAPI::FretDiagram::setBarre: fret %d must be > 0", fret);
     788            1 :         return;
     789              :     }
     790            1 :     if (ownership() == Ownership::SCORE) {
     791            1 :         fretDiagram()->undoSetFretBarre(string, fret, add);
     792              :     } else {
     793            0 :         fretDiagram()->setBarre(string, fret, add);
     794              :     }
     795              : }
     796              : 
     797            1 : void FretDiagram::clear()
     798              : {
     799            1 :     if (ownership() == Ownership::SCORE) {
     800            1 :         fretDiagram()->undoFretClear();
     801              :     } else {
     802            0 :         fretDiagram()->clear();
     803              :     }
     804            1 : }
     805              : 
     806            1 : QVariantList FretDiagram::dots() const
     807              : {
     808            1 :     QVariantList result;
     809            2 :     for (const auto& [string, dotVec] : fretDiagram()->dots()) {
     810            2 :         for (const mu::engraving::FretItem::Dot& d : dotVec) {
     811            1 :             if (!d.exists()) {
     812            0 :                 continue;
     813              :             }
     814            1 :             QVariantMap entry;
     815            1 :             entry["string"] = string;
     816            1 :             entry["fret"] = d.fret;
     817            1 :             entry["dotType"] = int(d.dtype);
     818            1 :             result.append(entry);
     819            1 :         }
     820              :     }
     821            1 :     return result;
     822            0 : }
     823              : 
     824            1 : QVariantList FretDiagram::markers() const
     825              : {
     826            1 :     QVariantList result;
     827            3 :     for (const auto& [string, m] : fretDiagram()->markers()) {
     828            2 :         if (!m.exists()) {
     829            1 :             continue;
     830              :         }
     831            1 :         QVariantMap entry;
     832            1 :         entry["string"] = string;
     833            1 :         entry["markerType"] = int(m.mtype);
     834            1 :         result.append(entry);
     835            1 :     }
     836            1 :     return result;
     837            0 : }
     838              : 
     839            1 : QVariantList FretDiagram::barres() const
     840              : {
     841            1 :     QVariantList result;
     842            2 :     for (const auto& [fret, b] : fretDiagram()->barres()) {
     843            1 :         if (!b.exists()) {
     844            0 :             continue;
     845              :         }
     846            1 :         QVariantMap entry;
     847            1 :         entry["fret"] = fret;
     848            1 :         entry["startString"] = b.startString;
     849            1 :         entry["endString"] = b.endString;
     850            1 :         result.append(entry);
     851            1 :     }
     852            1 :     return result;
     853            0 : }
     854              : 
     855              : //---------------------------------------------------------
     856              : //   wrap
     857              : ///   \cond PLUGIN_API \private \endcond
     858              : ///   Wraps mu::engraving::EngravingItem choosing the correct wrapper type
     859              : ///   at runtime based on the actual element type.
     860              : //---------------------------------------------------------
     861              : 
     862            8 : EngravingItem* mu::engraving::apiv1::wrap(mu::engraving::EngravingItem* e, Ownership own)
     863              : {
     864            8 :     if (!e) {
     865            0 :         return nullptr;
     866              :     }
     867              : 
     868              : #define API_WRAP(type) \
     869              :     if (e->is##type()) { return wrap<type>(to##type(e), own); }
     870              : 
     871            8 :     API_WRAP(Tie)
     872            8 :     API_WRAP(Ornament)
     873            8 :     API_WRAP(Note)
     874            8 :     API_WRAP(Chord)
     875            8 :     API_WRAP(ChordRest)
     876            8 :     API_WRAP(Tuplet)
     877            8 :     API_WRAP(DurationElement)
     878            8 :     API_WRAP(Beam)
     879            8 :     API_WRAP(Lyrics)
     880            8 :     API_WRAP(Harmony)
     881            7 :     API_WRAP(FretDiagram)
     882            0 :     API_WRAP(Segment)
     883            0 :     API_WRAP(Measure)
     884            0 :     API_WRAP(MeasureBase)
     885            0 :     API_WRAP(System)
     886            0 :     API_WRAP(Page)
     887            0 :     API_WRAP(SpannerSegment)
     888            0 :     API_WRAP(Spanner)
     889            0 :     return wrap<EngravingItem>(e, own);
     890              : 
     891              : #undef API_WRAP
     892              : }
        

Generated by: LCOV version 2.0-1