1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2018 Werner Schweer
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 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENCE.GPL
11 //=============================================================================
12 
13 #ifndef __SCOREDIFF_H__
14 #define __SCOREDIFF_H__
15 
16 #include "score.h"
17 
18 #include <vector>
19 
20 namespace Ms {
21 
22 enum class Pid;
23 class ScoreElement;
24 
25 //---------------------------------------------------------
26 //   ItemType
27 //---------------------------------------------------------
28 
29 enum class ItemType {
30       ELEMENT,
31       PROPERTY,
32       MARKUP,
33       CONTEXTCHANGE
34       };
35 
36 //---------------------------------------------------------
37 //   DiffType
38 //---------------------------------------------------------
39 #undef DELETE
40 enum class DiffType {
41       EQUAL,
42       INSERT,
43       DELETE,
44       REPLACE
45       };
46 
47 //---------------------------------------------------------
48 //   TextDiff
49 //    A structure similar to Diff from diff_match_patch
50 //    but contains info on line numbers of the diff
51 //---------------------------------------------------------
52 
53 struct TextDiff {
54       DiffType type;
55       QString text[2];
56       int start[2]; // starting line numbers in both texts
57       int end[2];   // ending line numbers in both texts
58 
59       bool merge(const TextDiff& other); // merge other diff into this one
60       QString toString(DiffType type, bool prefixLines = false) const;
61       QString toString(bool prefixLines = false) const { return toString(type, prefixLines); }
62       };
63 
64 //---------------------------------------------------------
65 //   BaseDiff
66 //---------------------------------------------------------
67 
68 struct BaseDiff {
69       DiffType type;
70       const TextDiff* textDiff;
71       const ScoreElement* ctx[2];
72       const ScoreElement* before[2];
73 
74       virtual ~BaseDiff() = default;
75 
76       virtual ItemType itemType() const = 0;
77       virtual bool sameItem(const BaseDiff&) const;
78       virtual Fraction afrac(int score) const;
79       virtual QString toString() const = 0;
80       };
81 
82 //---------------------------------------------------------
83 //   ContextChange
84 //    Dummy Diff for temporary storing information on
85 //    context changes.
86 //---------------------------------------------------------
87 
88 struct ContextChange : public BaseDiff {
itemTypeContextChange89       ItemType itemType() const override { return ItemType::CONTEXTCHANGE; }
90       QString toString() const override;
91       };
92 
93 //---------------------------------------------------------
94 //   ElementDiff
95 //---------------------------------------------------------
96 
97 struct ElementDiff : public BaseDiff {
98       const ScoreElement* el[2];
99 
itemTypeElementDiff100       ItemType itemType() const override { return ItemType::ELEMENT; }
101       bool sameItem(const BaseDiff&) const override;
102       Fraction afrac(int score) const override;
103       QString toString() const override;
104       };
105 
106 //---------------------------------------------------------
107 //   PropertyDiff
108 //---------------------------------------------------------
109 
110 struct PropertyDiff : public BaseDiff {
111       Pid pid;
112 
itemTypePropertyDiff113       ItemType itemType() const override { return ItemType::PROPERTY; }
114       bool sameItem(const BaseDiff&) const override;
115       QString toString() const override;
116       };
117 
118 //---------------------------------------------------------
119 //   MarkupDiff
120 //---------------------------------------------------------
121 
122 struct MarkupDiff : public BaseDiff {
123       QString name;
124       QVariant info;
125 
itemTypeMarkupDiff126       ItemType itemType() const override { return ItemType::MARKUP; }
127       bool sameItem(const BaseDiff&) const override;
128       QString toString() const override;
129       };
130 
131 //---------------------------------------------------------
132 //   ScoreDiff
133 //---------------------------------------------------------
134 
135 class ScoreDiff {
136       std::vector<TextDiff> _textDiffs; // raw diff between MSCX code for scores
137       std::vector<const TextDiff*> _mergedTextDiffs; // extra diff items created after merging score diff items
138       std::vector<BaseDiff*> _diffs;
139       Score* _s1;
140       Score* _s2;
141       ScoreContentState _scoreState1;
142       ScoreContentState _scoreState2;
143 
144       bool _textDiffOnly;
145 
146       void processMarkupDiffs();
147       void mergeInsertDeleteDiffs();
148       void mergeElementDiffs();
149       void editPropertyDiffs();
150 
151    public:
152       ScoreDiff(Score* s1, Score* s2, bool textDiffOnly = false);
153       ScoreDiff(const ScoreDiff&) = delete;
154       ~ScoreDiff();
155 
156       void update();
updated()157       bool updated() const { return _scoreState1 == _s1->state() && _scoreState2 == _s2->state(); }
158 
diffs()159       std::vector<BaseDiff*>& diffs() { return _diffs; }
textDiffs()160       const std::vector<TextDiff>& textDiffs() const { return _textDiffs; }
161 
score1()162       const Score* score1() const { return _s1; }
score2()163       const Score* score2() const { return _s2; }
164 
165       bool equal() const;
166 
167       QString rawDiff(bool skipEqual = true) const;
168       QString userDiff() const;
169       };
170 
171 }     // namespace Ms
172 #endif
173