1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2019 Werner Schweer and others
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19
20 #include "qmlpluginengine.h"
21 #include "api/qmlpluginapi.h"
22 #include "libmscore/score.h"
23 #include "musescore.h"
24
25 namespace Ms {
26
27 static constexpr int maxCmdCount = 10; // recursion prevention
28
29 //---------------------------------------------------------
30 // QmlPluginEngine
31 //---------------------------------------------------------
32
QmlPluginEngine(QObject * parent)33 QmlPluginEngine::QmlPluginEngine(QObject* parent)
34 : MsQmlEngine(parent)
35 {
36 PluginAPI::PluginAPI::registerQmlTypes();
37 }
38
39 //---------------------------------------------------------
40 // QmlPluginEngine::beginEndCmd
41 //---------------------------------------------------------
42
beginEndCmd(MuseScore * ms,bool inUndoRedo)43 void QmlPluginEngine::beginEndCmd(MuseScore* ms, bool inUndoRedo)
44 {
45 ++cmdCount;
46
47 if (inUndoRedo)
48 undoRedo = true;
49
50 const Score* cs = ms->currentScore();
51
52 // score and excerpts have united undo stack so we are better to track master score
53 currScoreState = cs ? cs->masterScore()->state() : ScoreContentState();
54
55 // TODO: most of plugins are never deleted so receivers usually never decrease
56 if (!receivers(SIGNAL(endCmd(const QMap<QString, QVariant>&))))
57 return;
58
59 endCmdInfo["selectionChanged"] = !cs || cs->selectionChanged();
60 endCmdInfo["excerptsChanged"] = !cs || cs->masterScore()->excerptsChanged();
61 endCmdInfo["instrumentsChanged"] = !cs || cs->masterScore()->instrumentsChanged();
62
63 endCmdInfo["startLayoutTick"] = cs ? cs->cmdState().startTick().ticks() : -1;
64 endCmdInfo["endLayoutTick"] = cs ? cs->cmdState().endTick().ticks() : -1;
65
66 endCmdInfo["undoRedo"] = undoRedo;
67 }
68
69 //---------------------------------------------------------
70 // QmlPluginEngine::endEndCmd
71 //---------------------------------------------------------
72
endEndCmd(MuseScore *)73 void QmlPluginEngine::endEndCmd(MuseScore*)
74 {
75 if (cmdCount >= maxCmdCount) {
76 QMessageBox::warning(mscore, tr("Plugin Error"), tr("Score update recursion limit reached (%1)").arg(maxCmdCount));
77 recursion = true;
78 }
79
80 if (!recursion)
81 emit endCmd(endCmdInfo);
82
83 --cmdCount;
84 if (!cmdCount) {
85 recursion = false;
86 undoRedo = false;
87 lastScoreState = currScoreState;
88 }
89 }
90
91 //---------------------------------------------------------
92 // QmlPluginEngine::inScoreChangeActionHandler
93 /// Returns \p true if the engine is in process of
94 /// handling endCmd() call which is a result of score
95 /// change user action (not undo/redo or simple selection
96 /// changes/mouse clicks etc.)
97 //---------------------------------------------------------
98
inScoreChangeActionHandler() const99 bool QmlPluginEngine::inScoreChangeActionHandler() const
100 {
101 return cmdCount > 0 && !undoRedo && currScoreState.isNewerThan(lastScoreState);
102 }
103 }
104