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 : #pragma once
23 :
24 : #include <functional>
25 : #include <set>
26 :
27 : #include <QList>
28 : #include <qqmlintegration.h>
29 :
30 : #include "async/asyncable.h"
31 :
32 : #include "engraving/dom/engravingitem.h"
33 : #include "engraving/dom/property.h"
34 :
35 : #include "internal/ielementrepositoryservice.h"
36 : #include "notation/inotation.h"
37 : #include "project/iprojectsession.h"
38 : #include "modularity/ioc.h"
39 : #include "propertyitem.h"
40 : #include "pointfpropertyitem.h"
41 : #include "ui/view/iconcodes.h"
42 : #include "types/commontypes.h"
43 : #include "rcommand/icommanddispatcher.h"
44 : #include "shortcuts_v2/icommandshortcutsregister.h"
45 :
46 : namespace mu::propertiespanel {
47 : using MeasurementUnits = CommonTypes::MeasurementUnits;
48 :
49 : class PropertiesPanelAbstractModel : public QObject, public muse::async::Asyncable, public muse::Contextable
50 : {
51 : Q_OBJECT
52 :
53 : Q_PROPERTY(QString title READ title NOTIFY titleChanged)
54 : Q_PROPERTY(int icon READ icon CONSTANT)
55 : Q_PROPERTY(PropertiesPanelSectionType sectionType READ sectionType CONSTANT)
56 : Q_PROPERTY(PropertiesPanelModelType modelType READ modelType CONSTANT)
57 : Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged)
58 :
59 : Q_PROPERTY(bool isSystemObjectBelowBottomStaff READ isSystemObjectBelowBottomStaff NOTIFY isSystemObjectBelowBottomStaffChanged)
60 : Q_PROPERTY(mu::propertiespanel::CommonTypes::MeasurementUnits measurementUnits READ measurementUnits NOTIFY measurementUnitsChanged)
61 :
62 : QML_ELEMENT;
63 : QML_UNCREATABLE("Not creatable as it is abstract base class")
64 :
65 : public:
66 : muse::GlobalInject<muse::shortcuts::ICommandShortcutsRegister> commandShortcutsRegister;
67 : muse::ContextInject<project::IProjectSession> context = { this };
68 : muse::ContextInject<muse::rcommand::ICommandDispatcher> commandDispatcher = { this };
69 :
70 : public:
71 : enum class PropertiesPanelSectionType {
72 : SECTION_UNDEFINED = -1,
73 : SECTION_GENERAL,
74 : SECTION_MEASURES,
75 : SECTION_NOTATION,
76 : SECTION_SYSTEM_PAGE_LAYOUT,
77 : SECTION_EMPTY_STAVES,
78 : SECTION_TEXT,
79 : SECTION_SCORE_DISPLAY,
80 : SECTION_SCORE_APPEARANCE,
81 : SECTION_PARTS,
82 : };
83 0 : Q_ENUM(PropertiesPanelSectionType)
84 :
85 : enum class PropertiesPanelModelType {
86 : TYPE_UNDEFINED = -1,
87 : TYPE_NOTE,
88 : TYPE_CHORD,
89 : TYPE_BEAM,
90 : TYPE_NOTEHEAD,
91 : TYPE_STEM,
92 : TYPE_HOOK,
93 : TYPE_FERMATA,
94 : TYPE_TEMPO,
95 : TYPE_A_TEMPO,
96 : TYPE_TEMPO_PRIMO,
97 : TYPE_GLISSANDO,
98 : TYPE_BARLINE,
99 : TYPE_BREATH,
100 : TYPE_MARKER,
101 : TYPE_SECTIONBREAK,
102 : TYPE_JUMP,
103 : TYPE_KEYSIGNATURE,
104 : TYPE_ACCIDENTAL,
105 : TYPE_ARPEGGIO,
106 : TYPE_CHORD_BRACKET,
107 : TYPE_FRET_DIAGRAM,
108 : TYPE_PEDAL,
109 : TYPE_SPACER,
110 : TYPE_CLEF,
111 : TYPE_HAIRPIN,
112 : TYPE_OTTAVA,
113 : TYPE_VOLTA,
114 : TYPE_VIBRATO,
115 : TYPE_SLUR,
116 : TYPE_HAMMER_ON_PULL_OFF,
117 : TYPE_TIE,
118 : TYPE_LAISSEZ_VIB,
119 : TYPE_PARTIAL_TIE,
120 : TYPE_CRESCENDO,
121 : TYPE_DIMINUENDO,
122 : TYPE_STAFF_TYPE_CHANGES,
123 : TYPE_TEXT_FRAME,
124 : TYPE_VERTICAL_FRAME,
125 : TYPE_HORIZONTAL_FRAME,
126 : TYPE_FRET_FRAME,
127 : TYPE_FRET_FRAME_CHORDS,
128 : TYPE_FRET_FRAME_SETTINGS,
129 : TYPE_ARTICULATION,
130 : TYPE_ORNAMENT,
131 : TYPE_TAPPING,
132 : TYPE_AMBITUS,
133 : TYPE_IMAGE,
134 : TYPE_CHORD_SYMBOL,
135 : TYPE_BRACKET,
136 : TYPE_TIME_SIGNATURE,
137 : TYPE_MMREST,
138 : TYPE_BEND,
139 : TYPE_TREMOLOBAR,
140 : TYPE_TREMOLO,
141 : TYPE_MEASURE_REPEAT,
142 : TYPE_DYNAMIC,
143 : TYPE_EXPRESSION,
144 : TYPE_TUPLET,
145 : TYPE_TEXT_LINE,
146 : TYPE_GRADUAL_TEMPO_CHANGE,
147 : TYPE_INSTRUMENT_NAME,
148 : TYPE_LYRICS,
149 : TYPE_LYRICS_LINE,
150 : TYPE_PARTIAL_LYRICS_LINE,
151 : TYPE_REST,
152 : TYPE_REST_BEAM,
153 : TYPE_REST_REST,
154 : TYPE_STRING_TUNINGS,
155 : TYPE_SYMBOL,
156 : TYPE_NOTELINE,
157 : TYPE_PLAY_COUNT_TEXT,
158 : };
159 0 : Q_ENUM(PropertiesPanelModelType)
160 :
161 : explicit PropertiesPanelAbstractModel(QObject* parent, const muse::modularity::ContextPtr& iocCtx,
162 : IElementRepositoryService* repository = nullptr,
163 : mu::engraving::ElementType elementType = mu::engraving::ElementType::INVALID);
164 :
165 : void init();
166 :
167 : QString title() const;
168 : int icon() const;
169 : PropertiesPanelSectionType sectionType() const;
170 : PropertiesPanelModelType modelType() const;
171 :
172 : static ElementKey makeKey(const mu::engraving::EngravingItem* item);
173 : static PropertiesPanelModelType modelTypeByElementKey(const ElementKey& elementKey);
174 : static std::set<PropertiesPanelModelType> modelTypesByElementKeys(const ElementKeySet& elementKeySet);
175 : static std::set<PropertiesPanelSectionType> sectionTypesByElementKeys(const ElementKeySet& elementKeySet, bool isRange,
176 : const QList<mu::engraving::EngravingItem*>& elementList = {});
177 : virtual bool isEmpty() const;
178 :
179 : virtual void createProperties() = 0;
180 : virtual void loadProperties() = 0;
181 :
182 : virtual void requestElements();
183 :
184 : virtual void disconnectAll();
185 :
186 : virtual void onCurrentNotationChanged();
187 :
188 : virtual void onNotationChanged(const mu::engraving::PropertyIdSet& changedPropertyIdSet,
189 : const mu::engraving::StyleIdSet& changedStyleIdSet);
190 :
191 : bool isSystemObjectBelowBottomStaff() const;
192 : MeasurementUnits measurementUnits() const;
193 :
194 : bool shouldUpdateOnScoreChange() const;
195 : virtual bool shouldUpdateWhenEmpty() const;
196 : virtual bool shouldUpdateOnEmptyPropertyAndStyleIdSets() const;
197 :
198 : mu::engraving::PropertyIdSet propertyIdSetFromStyleIdSet(const mu::engraving::StyleIdSet& styleIdSet) const;
199 :
200 : public slots:
201 : void setTitle(QString title);
202 : void setIcon(muse::ui::IconCode::Code icon);
203 : void setSectionType(PropertiesPanelSectionType sectionType);
204 : void setModelType(PropertiesPanelModelType modelType);
205 :
206 : signals:
207 : void titleChanged();
208 :
209 : void isEmptyChanged();
210 :
211 : void requestReloadPropertyItems();
212 :
213 : void requestReloadPropertiesPanelListModel();
214 :
215 : void isSystemObjectBelowBottomStaffChanged(bool isSystemObjectBelowBottomStaff);
216 : void measurementUnitsChanged(MeasurementUnits measurementUnits);
217 :
218 : protected:
219 : void setElementType(mu::engraving::ElementType type);
220 :
221 : PropertyItem* buildPropertyItem(const mu::engraving::Pid& pid, std::function<void(const mu::engraving::Pid propertyId,
222 : const QVariant& newValue)> onPropertyChangedCallBack =
223 : nullptr, std::function<void(const mu::engraving::Sid styleId,
224 : const
225 : QVariant& newValue)> onStyleChangedCallBack = nullptr,
226 : std::function<void(const mu::engraving::Pid propertyId)> onPropertyResetCallBack = nullptr);
227 : PointFPropertyItem* buildPointFPropertyItem(const mu::engraving::Pid& pid, std::function<void(const mu::engraving::Pid propertyId,
228 : const QVariant& newValue)>
229 : onPropertyChangedCallBack = nullptr,
230 : std::function<void(const mu::engraving::Pid propertyId)> onPropertyResetCallBack = nullptr);
231 :
232 : using ConvertPropertyValueFunc = std::function<QVariant (const QVariant&)>;
233 : void loadPropertyItem(PropertyItem* propertyItem, ConvertPropertyValueFunc convertElementPropertyValueFunc = nullptr);
234 : void loadPropertyItem(PropertyItem* propertyItem, const QList<engraving::EngravingItem*>& elements,
235 : ConvertPropertyValueFunc convertElementPropertyValueFunc = nullptr);
236 :
237 : bool isNotationExisting() const;
238 :
239 : engraving::PropertyValue valueToElementUnits(const mu::engraving::Pid& pid, const QVariant& value,
240 : const mu::engraving::EngravingItem* element) const;
241 : QVariant valueFromElementUnits(const mu::engraving::Pid& pid, const engraving::PropertyValue& value,
242 : const mu::engraving::EngravingItem* element) const;
243 :
244 : notation::INotationStylePtr style() const;
245 : bool updateStyleValue(const mu::engraving::Sid& sid, const QVariant& newValue);
246 : QVariant styleValue(const mu::engraving::Sid& sid) const;
247 :
248 : notation::INotationUndoStackPtr undoStack() const;
249 : void beginCommand(const muse::TranslatableString& actionName);
250 : void endCommand();
251 :
252 : void updateNotation();
253 : notation::INotationPtr currentNotation() const;
254 : bool isMasterNotation() const;
255 :
256 : notation::INotationSelectionPtr selection() const;
257 :
258 : IElementRepositoryService* m_repository = nullptr;
259 :
260 : QList<mu::engraving::EngravingItem*> m_elementList;
261 :
262 : QString shortcutsForCommand(const muse::rcommand::Command& command) const;
263 :
264 : protected slots:
265 : void onPropertyValueChanged(const mu::engraving::Pid pid, const QVariant& newValue);
266 : void setPropertyValue(const QList<mu::engraving::EngravingItem*>& items, const mu::engraving::Pid pid, const QVariant& newValue);
267 : void onPropertyValueReset(const mu::engraving::Pid pid);
268 : void resetPropertyValue(const QList<mu::engraving::EngravingItem*>& items, const mu::engraving::Pid pid);
269 : void updateProperties();
270 : void updateIsSystemObjectBelowBottomStaff();
271 : void updatemeasurementUnits();
272 :
273 : private:
274 : static bool showPartsSection(const QList<mu::engraving::EngravingItem*>& elementList);
275 :
276 : void initPropertyItem(PropertyItem* propertyItem, std::function<void(const mu::engraving::Pid propertyId,
277 : const QVariant& newValue)> onPropertyChangedCallBack = nullptr,
278 : std::function<void(const mu::engraving::Sid styleId,
279 : const
280 : QVariant& newValue)> onStyleChangedCallBack = nullptr,
281 : std::function<void(const mu::engraving::Pid propertyId)> onPropertyResetCallBack = nullptr);
282 :
283 : mu::engraving::Sid styleIdByPropertyId(const mu::engraving::Pid pid) const;
284 :
285 : QString m_title;
286 : muse::ui::IconCode::Code m_icon = muse::ui::IconCode::Code::NONE;
287 : PropertiesPanelSectionType m_sectionType = PropertiesPanelSectionType::SECTION_UNDEFINED;
288 : PropertiesPanelModelType m_modelType = PropertiesPanelModelType::TYPE_UNDEFINED;
289 : mu::engraving::ElementType m_elementType = mu::engraving::ElementType::INVALID;
290 : bool m_shouldUpdateOnScoreChange = true;
291 :
292 : bool m_isSystemObjectBelowBottomStaff = false;
293 : MeasurementUnits m_measurementUnits = MeasurementUnits::UNITS_UNKNOWN;
294 : };
295 :
296 : using PropertiesPanelModelType = PropertiesPanelAbstractModel::PropertiesPanelModelType;
297 : using PropertiesPanelSectionType = PropertiesPanelAbstractModel::PropertiesPanelSectionType;
298 : using PropertiesPanelModelTypeSet = std::set<PropertiesPanelModelType>;
299 : using PropertiesPanelSectionTypeSet = std::set<PropertiesPanelSectionType>;
300 : }
|