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 : #pragma once
24 :
25 : #include <QQmlEngine>
26 : #include <QQmlListProperty>
27 : #include <QVariant>
28 :
29 : #include "engraving/dom/engravingobject.h"
30 : #include "engraving/dom/property.h"
31 :
32 : namespace mu::engraving {
33 : class EngravingObject;
34 : }
35 :
36 : namespace mu::engraving::apiv1 {
37 : //---------------------------------------------------------
38 : // Ownership
39 : // Represents ownership policy regarding the underlying
40 : // engraving objects.
41 : //---------------------------------------------------------
42 : enum class Ownership {
43 : PLUGIN,
44 : SCORE,
45 : };
46 :
47 : /** APIDOC
48 : * Base class for API score elements
49 : * @class ScoreElement
50 : * @memberof Engraving
51 : * @hideconstructor
52 : */
53 : class ScoreElement : public QObject
54 : {
55 : Q_OBJECT
56 :
57 : /** APIDOC
58 : * Type of this element.
59 : * @readonly
60 : * @q_property {Engraving.ElementType}
61 : */
62 : Q_PROPERTY(QJSValue type READ type)
63 :
64 : /** APIDOC
65 : * Name of this element's type, not localized.
66 : * Use {@link Engraving.ScoreElement.userName} to obtain a localized
67 : * @readonly
68 : * @q_property {String}
69 : */
70 : Q_PROPERTY(QString name READ name)
71 :
72 : /** APIDOC
73 : * The size of a spatium for this element.
74 : * @readonly
75 : * @q_property {Number}
76 : * @since 4.6
77 : */
78 : Q_PROPERTY(float spatium READ spatium)
79 :
80 : /** APIDOC
81 : * The EID of this element.
82 : * @readonly
83 : * @q_property {String}
84 : * @since 4.6
85 : */
86 : Q_PROPERTY(QString eid READ eid)
87 :
88 : public:
89 42 : ScoreElement(mu::engraving::EngravingObject* m_e = nullptr, Ownership own = Ownership::PLUGIN)
90 42 : : QObject(), e(m_e), m_ownership(own) {}
91 : ScoreElement(const ScoreElement&) = delete;
92 : ScoreElement& operator=(const ScoreElement&) = delete;
93 : virtual ~ScoreElement();
94 :
95 4 : Ownership ownership() const { return m_ownership; }
96 0 : void setOwnership(Ownership o) { m_ownership = o; }
97 :
98 0 : mu::engraving::EngravingObject* element() { return e; }
99 0 : const mu::engraving::EngravingObject* element() const { return e; }
100 :
101 : QString name() const;
102 : QJSValue type() const;
103 : qreal spatium() const;
104 0 : QString eid() const { return QString::fromStdString(element()->eid().toStdString()); }
105 :
106 : QVariant get(mu::engraving::Pid pid) const;
107 : void set(mu::engraving::Pid pid, const QVariant& val);
108 : void reset(mu::engraving::Pid pid);
109 :
110 : /** APIDOC
111 : * Name of this element's type, localized.
112 : * @method
113 : * @return {String} name
114 : */
115 : Q_INVOKABLE QString userName() const;
116 :
117 : /** APIDOC
118 : * Checks whether two variables represent the same object
119 : * @method
120 : * @param {Engraving.ScoreElement} other Object for comparison
121 : * @return {Boolean} result
122 : */
123 0 : Q_INVOKABLE bool is(apiv1::ScoreElement* other) { return other && element() == other->element(); }
124 :
125 : int apiversion() const;
126 :
127 : protected:
128 : mu::engraving::EngravingObject* const e;
129 :
130 : private:
131 : Ownership m_ownership;
132 : mutable int m_apiversion = -1;
133 : };
134 :
135 : template<class Wrapper, class T>
136 11 : Wrapper* wrap(T* t, Ownership own = Ownership::SCORE)
137 : {
138 11 : Wrapper* w = t ? new Wrapper(t, own) : nullptr;
139 : // All wrapper objects should belong to JavaScript code.
140 11 : QQmlEngine::setObjectOwnership(w, QQmlEngine::JavaScriptOwnership);
141 11 : return w;
142 : }
143 :
144 : extern ScoreElement* wrap(mu::engraving::EngravingObject* se, Ownership own = Ownership::SCORE);
145 :
146 : // Can be used to construct wrappers which do not
147 : // support standard ownership logic or require
148 : // additional arguments for initialization.
149 : template<class Wrapper, class T, typename ... Args>
150 0 : Wrapper* customWrap(T* t, Args... args)
151 : {
152 0 : Wrapper* w = t ? new Wrapper(t, std::forward<Args>(args)...) : nullptr;
153 : // All wrapper objects should belong to JavaScript code.
154 0 : QQmlEngine::setObjectOwnership(w, QQmlEngine::JavaScriptOwnership);
155 0 : return w;
156 : }
157 :
158 : // QML access to containers.
159 : // A wrapper which provides read-only access for various
160 : // items containers.
161 : template<typename T, class Container>
162 : class QmlListAccess : public QQmlListProperty<T>
163 : {
164 : public:
165 1 : QmlListAccess(QObject* obj, Container& container)
166 : : QQmlListProperty<T>(obj,
167 : const_cast<void*>(static_cast<const void*>(&container)),
168 : &count,
169 1 : &at) {}
170 :
171 1 : static qsizetype count(QQmlListProperty<T>* l)
172 : {
173 1 : return static_cast<Container*>(l->data)->size();
174 : }
175 :
176 0 : static T* at(QQmlListProperty<T>* l, qsizetype i)
177 : {
178 0 : auto el = static_cast<Container*>(l->data)->at(i);
179 : // If a polymorphic wrap() function is available
180 : // for the requested type, use it for wrapping.
181 : if constexpr (std::is_same<T*, decltype(wrap(el, Ownership::SCORE))>::value) {
182 0 : return static_cast<T*>(wrap(el, Ownership::SCORE));
183 : } else { // Otherwise, wrap directly to the requested wrapper type.
184 0 : return wrap<T>(el, Ownership::SCORE);
185 : }
186 : }
187 : };
188 :
189 : template<typename T, class Container>
190 1 : QmlListAccess<T, Container> wrapContainerProperty(const QObject* obj, Container& c)
191 : {
192 1 : return QmlListAccess<T, Container>(const_cast<QObject*>(obj), c);
193 : }
194 : }
|