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 "durationelement.h"
24 :
25 : #include "property.h"
26 : #include "score.h"
27 : #include "staff.h"
28 : #include "tuplet.h"
29 :
30 : #include "editing/transaction/undostack.h"
31 :
32 : using namespace mu;
33 : using namespace mu::engraving;
34 :
35 : namespace mu::engraving {
36 : //---------------------------------------------------------
37 : // DurationElement
38 : //---------------------------------------------------------
39 :
40 53137 : DurationElement::DurationElement(const ElementType& type, EngravingObject* parent, ElementFlags f)
41 53137 : : EngravingItem(type, parent, f)
42 : {
43 53137 : m_tuplet = 0;
44 53137 : }
45 :
46 : //---------------------------------------------------------
47 : // DurationElement
48 : //---------------------------------------------------------
49 :
50 5081 : DurationElement::DurationElement(const DurationElement& e, bool link)
51 5081 : : EngravingItem(e, link)
52 : {
53 5081 : m_tuplet = 0; // e._tuplet;
54 5081 : m_duration = e.m_duration;
55 5081 : }
56 :
57 : //---------------------------------------------------------
58 : // ~DurationElement
59 : //---------------------------------------------------------
60 :
61 51675 : DurationElement::~DurationElement()
62 : {
63 51675 : if (m_tuplet) {
64 2379 : setTuplet(nullptr);
65 : }
66 51675 : }
67 :
68 : //---------------------------------------------------------
69 : // topTuplet
70 : //---------------------------------------------------------
71 :
72 121033 : Tuplet* DurationElement::topTuplet() const
73 : {
74 121033 : Tuplet* t = tuplet();
75 121033 : if (t) {
76 9075 : while (t->tuplet()) {
77 1888 : t = t->tuplet();
78 : }
79 : }
80 121033 : return t;
81 : }
82 :
83 : //---------------------------------------------------------
84 : // globalTicks
85 : //---------------------------------------------------------
86 :
87 1500004 : Fraction DurationElement::globalTicks() const
88 : {
89 1500004 : Fraction f(m_duration);
90 1698624 : for (Tuplet* t = tuplet(); t; t = t->tuplet()) {
91 198620 : f /= t->ratio();
92 : }
93 1500004 : return f;
94 : }
95 :
96 28 : float DurationElement::timeStretchFactor() const
97 : {
98 28 : int nominalDuration = m_duration.ticks();
99 28 : int actualDuration = actualTicks().ticks();
100 :
101 28 : return actualDuration / static_cast<float>(nominalDuration);
102 : }
103 :
104 : //---------------------------------------------------------
105 : // actualTicks
106 : //---------------------------------------------------------
107 :
108 1447997 : Fraction DurationElement::actualTicksAt(const Fraction& tick) const
109 : {
110 : // Use when tick() is unreliable, for example when pasting
111 1447997 : return globalTicks() / staff()->timeStretch(tick);
112 : }
113 :
114 1445786 : Fraction DurationElement::actualTicks() const
115 : {
116 1445786 : return actualTicksAt(tick());
117 : }
118 :
119 : //---------------------------------------------------------
120 : // readAddTuplet
121 : //---------------------------------------------------------
122 :
123 142 : void DurationElement::readAddTuplet(Tuplet* t)
124 : {
125 142 : setTuplet(t);
126 142 : if (!score()->undoStack()->hasActiveTransaction()) { // HACK, also added in Undo::AddElement()
127 0 : t->add(this);
128 : }
129 142 : }
130 :
131 10196 : void DurationElement::setTuplet(Tuplet* t)
132 : {
133 10196 : if (m_tuplet) {
134 4115 : m_tuplet->removeDurationElement(this);
135 : }
136 :
137 10196 : m_tuplet = t;
138 :
139 10196 : if (m_tuplet) {
140 5657 : m_tuplet->addDurationElement(this);
141 : }
142 10196 : }
143 :
144 : //---------------------------------------------------------
145 : // getProperty
146 : //---------------------------------------------------------
147 :
148 345903 : PropertyValue DurationElement::getProperty(Pid propertyId) const
149 : {
150 345903 : switch (propertyId) {
151 522 : case Pid::DURATION:
152 522 : return PropertyValue::fromValue(m_duration);
153 345381 : default:
154 345381 : return EngravingItem::getProperty(propertyId);
155 : }
156 : }
157 :
158 : //---------------------------------------------------------
159 : // setProperty
160 : //---------------------------------------------------------
161 :
162 8185 : bool DurationElement::setProperty(Pid propertyId, const PropertyValue& v)
163 : {
164 8185 : switch (propertyId) {
165 198 : case Pid::DURATION: {
166 198 : Fraction f(v.value<Fraction>());
167 198 : setTicks(f);
168 198 : triggerLayout();
169 : }
170 198 : break;
171 7987 : default:
172 7987 : return EngravingItem::setProperty(propertyId, v);
173 : }
174 198 : return true;
175 : }
176 : }
|