Skip to content

Commit

Permalink
Plugin API: merge changes from onScoreStateChanged with user action i…
Browse files Browse the repository at this point in the history
…n undo stack
  • Loading branch information
dmitrio95 committed Jan 20, 2020
1 parent 43d0e47 commit e3d44b6
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 12 deletions.
2 changes: 1 addition & 1 deletion libmscore/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ bool Score::dirty() const

ScoreContentState Score::state() const
{
return std::make_pair(this, undoStack()->state());
return ScoreContentState(this, undoStack()->state());
}

//---------------------------------------------------------
Expand Down
13 changes: 12 additions & 1 deletion libmscore/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,18 @@ class UpdateState {
// ScoreContentState
//---------------------------------------------------------

typedef std::pair<const Score*, int> ScoreContentState;
class ScoreContentState {
const Score* score;
int num;
public:
ScoreContentState() : score(nullptr), num(0) {}
ScoreContentState(const Score* s, int stateNum) : score(s), num(stateNum) {}

bool operator==(const ScoreContentState& s2) const { return score == s2.score && num == s2.num; }
bool operator!=(const ScoreContentState& s2) const { return !(*this == s2); }

bool isNewerThan(const ScoreContentState& s2) const { return score == s2.score && num > s2.num; }
};

class MasterScore;

Expand Down
6 changes: 3 additions & 3 deletions mscore/musescore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4832,7 +4832,7 @@ void MuseScore::undoRedo(bool undo)
cv->changeState(ViewState::NORMAL);
cv->startUndoRedo(undo);
updateInputState(cs);
endCmd();
endCmd(/* undoRedo */ true);
if (pianorollEditor)
pianorollEditor->update();
}
Expand Down Expand Up @@ -5813,10 +5813,10 @@ void MuseScore::cmd(QAction* a)
// Updates the UI after a possible score change.
//---------------------------------------------------------

void MuseScore::endCmd()
void MuseScore::endCmd(bool undoRedo)
{
#ifdef SCRIPT_INTERFACE
getPluginEngine()->beginEndCmd(this);
getPluginEngine()->beginEndCmd(this, undoRedo);
#endif
if (timeline())
timeline()->updateGrid();
Expand Down
3 changes: 2 additions & 1 deletion mscore/musescore.h
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,8 @@ class MuseScore : public QMainWindow, public MuseScoreCore {

Q_INVOKABLE void openExternalLink(const QString&);

virtual void endCmd() override;
void endCmd(bool undoRedo);
void endCmd() override { endCmd(false); };
void printFile();
void exportFile();
bool exportParts();
Expand Down
22 changes: 22 additions & 0 deletions mscore/plugin/api/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include "libmscore/segment.h"
#include "libmscore/text.h"

#include "musescore.h"
#include "../qmlpluginengine.h"

namespace Ms {
namespace PluginAPI {

Expand Down Expand Up @@ -118,5 +121,24 @@ Measure* Score::lastMeasureMM()
return wrap<Measure>(score()->lastMeasureMM(), Ownership::SCORE);
}

//---------------------------------------------------------
// Score::startCmd
//---------------------------------------------------------

void Score::startCmd()
{
// TODO: should better use qmlEngine(this) (need to set context for wrappers then)
const QmlPluginEngine* engine = mscore->getPluginEngine();
if (engine->inScoreChangeActionHandler()) {
// Plugin-originated changes made while handling onScoreStateChanged
// should be grouped together with the action which caused this change
// (if it was caused by actual score change).
if (!score()->undoStack()->active())
score()->undoStack()->reopen();
}
else {
score()->startCmd();
}
}
}
}
2 changes: 1 addition & 1 deletion mscore/plugin/api/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class Score : public Ms::PluginAPI::ScoreElement {
* least once by "dock" type plugins in case they
* modify the score.
*/
Q_INVOKABLE void startCmd() { score()->startCmd(); }
Q_INVOKABLE void startCmd();
/**
* For "dock" type plugins: to be used after score
* modifications to make them undoable.
Expand Down
30 changes: 26 additions & 4 deletions mscore/plugin/qmlpluginengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,28 @@ QmlPluginEngine::QmlPluginEngine(QObject* parent)
// QmlPluginEngine::beginEndCmd
//---------------------------------------------------------

void QmlPluginEngine::beginEndCmd(MuseScore* ms)
void QmlPluginEngine::beginEndCmd(MuseScore* ms, bool inUndoRedo)
{
++cmdCount;

if (inUndoRedo)
undoRedo = true;

const Score* cs = ms->currentScore();
currScoreState = cs->masterScore()->state(); // score and excerpts have united undo stack so we are better to track master score

// TODO: most of plugins are never deleted so receivers usually never decrease
if (!receivers(SIGNAL(endCmd(const QMap<QString, QVariant>&))))
return;

const Score* cs = ms->currentScore();

endCmdInfo["selectionChanged"] = !cs || cs->selectionChanged();
endCmdInfo["excerptsChanged"] = !cs || cs->masterScore()->excerptsChanged();
endCmdInfo["instrumentsChanged"] = !cs || cs->masterScore()->instrumentsChanged();

endCmdInfo["startLayoutTick"] = cs ? cs->cmdState().startTick().ticks() : -1;
endCmdInfo["endLayoutTick"] = cs ? cs->cmdState().endTick().ticks() : -1;

endCmdInfo["undoRedo"] = undoRedo;
}

//---------------------------------------------------------
Expand All @@ -73,7 +79,23 @@ void QmlPluginEngine::endEndCmd(MuseScore*)
emit endCmd(endCmdInfo);

--cmdCount;
if (!cmdCount)
if (!cmdCount) {
recursion = false;
undoRedo = false;
lastScoreState = currScoreState;
}
}

//---------------------------------------------------------
// QmlPluginEngine::inScoreChangeActionHandler
/// Returns \p true if the engine is in process of
/// handling endCmd() call which is a result of score
/// change user action (not undo/redo or simple selection
/// changes/mouse clicks etc.)
//---------------------------------------------------------

bool QmlPluginEngine::inScoreChangeActionHandler() const
{
return cmdCount > 0 && !undoRedo && currScoreState.isNewerThan(lastScoreState);
}
}
9 changes: 8 additions & 1 deletion mscore/plugin/qmlpluginengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define __QMLPLUGINENGINE_H__

#include "../qml/msqmlengine.h"
#include "libmscore/score.h"

namespace Ms {

Expand All @@ -36,14 +37,20 @@ class QmlPluginEngine : public MsQmlEngine {
QMap<QString, QVariant> endCmdInfo;
int cmdCount = 0;
bool recursion = false;
bool undoRedo = false;

ScoreContentState lastScoreState;
ScoreContentState currScoreState;

signals:
void endCmd(const QMap<QString, QVariant>& changes);
public:
QmlPluginEngine(QObject* parent = nullptr);

void beginEndCmd(MuseScore*);
void beginEndCmd(MuseScore*, bool undoRedo);
void endEndCmd(MuseScore*);

bool inScoreChangeActionHandler() const;
};

} // namespace Ms
Expand Down

0 comments on commit e3d44b6

Please sign in to comment.