LCOV - code coverage report
Current view: top level - src/engraving/api/v1 - scoreelement.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 17.3 % 133 23
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 "scoreelement.h"
      24              : 
      25              : #include "engraving/dom/measure.h"
      26              : #include "engraving/dom/range.h"
      27              : #include "engraving/dom/engravingobject.h"
      28              : #include "engraving/dom/score.h"
      29              : 
      30              : // api
      31              : #include "apitypes.h"
      32              : #include "apistructs.h"
      33              : #include "score.h"
      34              : #include "part.h"
      35              : #include "elements.h"
      36              : 
      37              : #include "log.h"
      38              : 
      39              : using namespace mu::engraving::apiv1;
      40              : 
      41           40 : ScoreElement::~ScoreElement()
      42              : {
      43           40 :     if (m_ownership == Ownership::PLUGIN) {
      44            0 :         delete e;
      45              :     }
      46           40 : }
      47              : 
      48            0 : int ScoreElement::apiversion() const
      49              : {
      50            0 :     if (m_apiversion == -1) {
      51            0 :         QJSEngine* engine = qjsEngine(this);
      52            0 :         IF_ASSERT_FAILED(engine) {
      53            0 :             return -1;
      54              :         }
      55              : 
      56            0 :         m_apiversion = engine->property("apiversion").toInt();
      57            0 :         IF_ASSERT_FAILED(m_apiversion > 0) {
      58            0 :             m_apiversion = -1;
      59              :         }
      60              :     }
      61            0 :     return m_apiversion;
      62              : }
      63              : 
      64            0 : QString ScoreElement::name() const
      65              : {
      66            0 :     return QString(e->typeName());
      67              : }
      68              : 
      69            0 : QJSValue ScoreElement::type() const
      70              : {
      71            0 :     if (apiversion() == 1) {
      72            0 :         return QJSValue(int(e->type()));
      73              :     } else {
      74            0 :         static const QMetaEnum meta = QMetaEnum::fromType<enums::ElementType>();
      75            0 :         return QJSValue(QString(meta.valueToKey(int(e->type()))));
      76              :     }
      77              : }
      78              : 
      79              : //---------------------------------------------------------
      80              : //   ScoreElement::userName
      81              : ///   \brief Human-readable element type name
      82              : ///   \returns Name of the element type, translated
      83              : ///   according to the current MuseScore locale settings.
      84              : //---------------------------------------------------------
      85              : 
      86            0 : QString ScoreElement::userName() const
      87              : {
      88            0 :     return e->translatedTypeUserName();
      89              : }
      90              : 
      91              : //---------------------------------------------------------
      92              : //   ScoreElement::spatium
      93              : //---------------------------------------------------------
      94              : 
      95            0 : qreal ScoreElement::spatium() const
      96              : {
      97            0 :     return e->isEngravingItem() ? toEngravingItem(e)->spatium() : e->score()->style().spatium();
      98              : }
      99              : 
     100              : //---------------------------------------------------------
     101              : //   ScoreElement::get
     102              : ///   Returns an engraving property converted to a plugin-readable value.
     103              : //---------------------------------------------------------
     104              : 
     105            8 : QVariant ScoreElement::get(mu::engraving::Pid pid) const
     106              : {
     107            8 :     if (!e) {
     108            0 :         return QVariant();
     109              :     }
     110            8 :     const PropertyValue val = e->getProperty(pid);
     111            8 :     switch (val.type()) {
     112            0 :     case P_TYPE::FRACTION: {
     113            0 :         const mu::engraving::Fraction f(val.value<mu::engraving::Fraction>());
     114            0 :         return QVariant::fromValue(wrap(f));
     115              :     }
     116            0 :     case P_TYPE::ORNAMENT_INTERVAL: {
     117            0 :         const OrnamentInterval o(val.value<OrnamentInterval>());
     118            0 :         return QVariant::fromValue(wrap(o));
     119              :     }
     120            0 :     case P_TYPE::POINT:
     121            0 :         return val.value<PointF>().toQPointF() / spatium();
     122            0 :     case P_TYPE::PAIR_REAL: {
     123            0 :         const PairF pair = val.value<PairF>();
     124            0 :         return QVariantList { pair.first, pair.second };
     125              :     }
     126            0 :     case P_TYPE::ABSOLUTE:
     127            0 :         return val.toReal() / spatium();
     128            0 :     case P_TYPE::SPATIUM:
     129            0 :         return val.value<Spatium>().val();
     130            8 :     default:
     131            8 :         break;
     132              :     }
     133            8 :     return val.toQVariant();
     134            8 : }
     135              : 
     136            0 : static mu::engraving::AlignH alignHFromApiValue(enums::Align apiValue)
     137              : {
     138            0 :     switch (apiValue & enums::Align::HMASK) {
     139            0 :     case enums::Align::LEFT: return mu::engraving::AlignH::LEFT;
     140            0 :     case enums::Align::RIGHT: return mu::engraving::AlignH::RIGHT;
     141            0 :     case enums::Align::HCENTER: return mu::engraving::AlignH::HCENTER;
     142            0 :     default:
     143            0 :         break;
     144              :     }
     145              : 
     146            0 :     return mu::engraving::AlignH::LEFT;
     147              : }
     148              : 
     149            0 : static mu::engraving::AlignV alignVFromApiValue(enums::Align apiValue)
     150              : {
     151            0 :     switch (apiValue & enums::Align::VMASK) {
     152            0 :     case enums::Align::TOP: return mu::engraving::AlignV::TOP;
     153            0 :     case enums::Align::BOTTOM: return mu::engraving::AlignV::BOTTOM;
     154            0 :     case enums::Align::VCENTER: return mu::engraving::AlignV::VCENTER;
     155            0 :     case enums::Align::BASELINE: return mu::engraving::AlignV::BASELINE;
     156            0 :     default:
     157            0 :         break;
     158              :     }
     159              : 
     160            0 :     return mu::engraving::AlignV::TOP;
     161              : }
     162              : 
     163              : //---------------------------------------------------------
     164              : //   ScoreElement::set
     165              : //---------------------------------------------------------
     166              : 
     167            6 : void ScoreElement::set(mu::engraving::Pid pid, const QVariant& val)
     168              : {
     169            6 :     if (!e) {
     170            0 :         return;
     171              :     }
     172              : 
     173            6 :     PropertyValue newValue;
     174              : 
     175            6 :     switch (propertyType(pid)) {
     176            0 :     case P_TYPE::FRACTION: {
     177            0 :         Fraction* f = val.value<Fraction*>();
     178            0 :         if (!f) {
     179            0 :             LOGW() << "trying to assign value of wrong type to fractional property";
     180            0 :             return;
     181              :         }
     182              :         // Pid::TIMESIG_ACTUAL is only set when we change the time signature,
     183              :         // aside from that it's read-only. What the user intends to do here is
     184              :         // change the actual length of the measure, so we do that instead.
     185            0 :         if (pid == Pid::TIMESIG_ACTUAL && e->isMeasure() && m_ownership == Ownership::SCORE) {
     186            0 :             mu::engraving::Measure* m = toMeasure(e);
     187            0 :             if (m->ticks() != f->fraction()) {
     188            0 :                 mu::engraving::ScoreRange range;
     189            0 :                 range.read(m->first(), m->last());
     190            0 :                 m->adjustToLen(f->fraction());
     191            0 :             }
     192            0 :             return;
     193              :         }
     194            0 :         newValue = f->fraction();
     195              :     }
     196            0 :     break;
     197            0 :     case P_TYPE::ORNAMENT_INTERVAL: {
     198            0 :         OrnamentIntervalWrapper* o = val.value<OrnamentIntervalWrapper*>();
     199            0 :         if (!o) {
     200            0 :             LOGW() << "trying to assign value of wrong type to fractional property";
     201            0 :             return;
     202              :         }
     203            0 :         newValue = o->ornamentInterval();
     204              :     }
     205            0 :     break;
     206            0 :     case P_TYPE::POINT:
     207            0 :         newValue = PointF::fromQPointF(val.toPointF() * spatium());
     208            0 :         break;
     209            0 :     case P_TYPE::ABSOLUTE:
     210            0 :         newValue = val.toReal() * spatium();
     211            0 :         break;
     212            0 :     case P_TYPE::ALIGN: {
     213            0 :         apiv1::enums::Align apiValue = apiv1::enums::Align(val.toInt());
     214              : 
     215            0 :         newValue = Align { alignHFromApiValue(apiValue), alignVFromApiValue(apiValue) };
     216            0 :     } break;
     217              : 
     218            6 :     default:
     219            6 :         newValue = PropertyValue::fromQVariant(val, propertyType(pid));
     220            6 :         break;
     221              :     }
     222              : 
     223            6 :     const PropertyFlags f = e->propertyFlags(pid);
     224            6 :     const PropertyFlags newFlags = (f == PropertyFlags::NOSTYLE) ? f : PropertyFlags::UNSTYLED;
     225              : 
     226            6 :     if (m_ownership == Ownership::SCORE) {
     227            6 :         e->undoChangeProperty(pid, newValue, newFlags);
     228              :     } else { // not added to a score so no need (and dangerous) to deal with undo stack
     229            0 :         e->setProperty(pid, newValue);
     230            0 :         e->setPropertyFlags(pid, newFlags);
     231              :     }
     232            6 : }
     233              : 
     234            0 : void ScoreElement::reset(mu::engraving::Pid pid)
     235              : {
     236            0 :     if (!e) {
     237            0 :         return;
     238              :     }
     239              : 
     240            0 :     if (m_ownership == Ownership::SCORE) {
     241            0 :         e->undoResetProperty(pid);
     242              :     } else {
     243            0 :         e->resetProperty(pid);
     244              :     }
     245              : }
     246              : 
     247              : //---------------------------------------------------------
     248              : //   wrap
     249              : ///   \cond PLUGIN_API \private \endcond
     250              : ///   Wraps mu::engraving::ScoreElement choosing the correct wrapper
     251              : ///   type at runtime based on the actual element type.
     252              : //---------------------------------------------------------
     253              : 
     254            0 : ScoreElement* mu::engraving::apiv1::wrap(mu::engraving::EngravingObject* se, Ownership own)
     255              : {
     256            0 :     if (!se) {
     257            0 :         return nullptr;
     258              :     }
     259            0 :     if (se->isEngravingItem()) {
     260            0 :         return wrap(toEngravingItem(se), own);
     261              :     }
     262              : 
     263              :     using mu::engraving::ElementType;
     264            0 :     switch (se->type()) {
     265            0 :     case ElementType::SCORE:
     266            0 :         return wrap<mu::engraving::apiv1::Score>(toScore(se), own);
     267            0 :     case ElementType::PART:
     268            0 :         return wrap<mu::engraving::apiv1::Part>(toPart(se), own);
     269            0 :     case ElementType::STAFF:
     270            0 :         return wrap<mu::engraving::apiv1::Staff>(toStaff(se), own);
     271            0 :     default:
     272            0 :         break;
     273              :     }
     274            0 :     return wrap<ScoreElement>(se, own);
     275              : }
        

Generated by: LCOV version 2.0-1