1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2004-2011 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 __XML_H__
14 #define __XML_H__
15 
16 #include <QMultiMap>
17 
18 #include "connector.h"
19 #include "stafftype.h"
20 #include "interval.h"
21 #include "element.h"
22 #include "select.h"
23 
24 namespace Ms {
25 
26 enum class PlaceText : char;
27 enum class ClefType : signed char;
28 class Spanner;
29 class Beam;
30 class Tuplet;
31 class Measure;
32 class LinkedElements;
33 
34 //---------------------------------------------------------
35 //   SpannerValues
36 //---------------------------------------------------------
37 
38 struct SpannerValues {
39       int spannerId;
40       Fraction tick2;
41       int track2;
42       };
43 
44 //---------------------------------------------------------
45 //   TextStyleMap
46 //---------------------------------------------------------
47 
48 struct TextStyleMap {
49       QString name;
50       Tid ss;
51       };
52 
53 //---------------------------------------------------------
54 //   LinksIndexer
55 //---------------------------------------------------------
56 
57 class LinksIndexer {
58       int _lastLocalIndex              { -1                    };
59       Location _lastLinkedElementLoc   { Location::absolute()  };
60 
61    public:
62       int assignLocalIndex(const Location& mainElementInfo);
63       };
64 
65 //---------------------------------------------------------
66 //   XmlReader
67 //---------------------------------------------------------
68 
69 class XmlReader : public QXmlStreamReader {
70       QString docName;  // used for error reporting
71 
72       // Score read context (for read optimizations):
73       Fraction _tick             { Fraction(0, 1) };
74       Fraction _tickOffset       { Fraction(0, 1) };
75       int _intTick          { 0       };
76       int _track            { 0       };
77       int _trackOffset      { 0       };
78       bool _pasteMode       { false   };        // modifies read behaviour on paste operation
79       Measure* _lastMeasure { 0       };
80       Measure* _curMeasure  { 0       };
81       int _curMeasureIdx    { 0       };
82       QHash<int, Beam*>    _beams;
83       QHash<int, Tuplet*>  _tuplets;
84 
85       QList<SpannerValues> _spannerValues;
86       QList<std::pair<int,Spanner*>> _spanner;
87       QList<StaffType> _staffTypes;
88       QList<std::pair<Element*, QPointF>> _fixOffsets;
89 
90       std::vector<std::unique_ptr<ConnectorInfoReader>> _connectors;
91       std::vector<std::unique_ptr<ConnectorInfoReader>> _pendingConnectors; // connectors that are pending to be updated and added to _connectors. That will happen when checkConnectors() is called.
92 
93       void htmlToString(int level, QString*);
94       Interval _transpose;
95       QMap<int, LinkedElements*> _elinks; // for reading old files (< 3.01)
96       QMap<int, QList<QPair<LinkedElements*, Location>>> _staffLinkedElements; // one list per staff
97       LinksIndexer _linksIndexer;
98       QMultiMap<int, int> _tracks;
99 
100       QList<TextStyleMap> userTextStyles;
101 
102       void addConnectorInfo(std::unique_ptr<ConnectorInfoReader>);
103       void removeConnector(const ConnectorInfoReader*); // Removes the whole ConnectorInfo chain from the connectors list.
104 
105       qint64 _offsetLines { 0 };
106 
107    public:
XmlReader(QFile * f)108       XmlReader(QFile* f) : QXmlStreamReader(f), docName(f->fileName()) {}
QXmlStreamReader(d)109       XmlReader(const QByteArray& d, const QString& st = QString()) : QXmlStreamReader(d), docName(st)  {}
QXmlStreamReader(d)110       XmlReader(QIODevice* d, const QString& st = QString()) : QXmlStreamReader(d), docName(st) {}
QXmlStreamReader(d)111       XmlReader(const QString& d, const QString& st = QString()) : QXmlStreamReader(d), docName(st) {}
112       XmlReader(const XmlReader&) = delete;
113       XmlReader& operator=(const XmlReader&) = delete;
114       ~XmlReader();
115 
116       bool hasAccidental { false };                     // used for userAccidental backward compatibility
117       void unknown();
118 
119       // attribute helper routines:
attribute(const char * s)120       QString attribute(const char* s) const { return attributes().value(s).toString(); }
121       QString attribute(const char* s, const QString&) const;
122       int intAttribute(const char* s) const;
123       int intAttribute(const char* s, int _default) const;
124       double doubleAttribute(const char* s) const;
125       double doubleAttribute(const char* s, double _default) const;
126       bool hasAttribute(const char* s) const;
127 
128       // helper routines based on readElementText():
readInt()129       int readInt()            { return readElementText().toInt();      }
readInt(bool * ok)130       int readInt(bool* ok)    { return readElementText().toInt(ok);    }
readIntHex()131       int readIntHex()         { return readElementText().toInt(0, 16); }
readDouble()132       double readDouble()      { return readElementText().toDouble();   }
readLongLong()133       qlonglong readLongLong() { return readElementText().toLongLong(); }
134 
135       double readDouble(double min, double max);
136       bool readBool();
137       QPointF readPoint();
138       QSizeF readSize();
139       QRectF readRect();
140       QColor readColor();
141       Fraction readFraction();
142       QString readXml();
143 
setDocName(const QString & s)144       void setDocName(const QString& s) { docName = s; }
getDocName()145       QString getDocName() const        { return docName; }
146 
tick()147       Fraction tick()  const            { return _tick + _tickOffset; }
148       Fraction rtick()  const ;
tickOffset()149       Fraction tickOffset() const       { return _tickOffset; }
150       void setTick(const Fraction& f);
151       void incTick(const Fraction& f);
setTickOffset(const Fraction & val)152       void setTickOffset(const Fraction& val) { _tickOffset = val; }
153 
track()154       int track() const            { return _track + _trackOffset;     }
setTrackOffset(int val)155       void setTrackOffset(int val) { _trackOffset = val;   }
trackOffset()156       int trackOffset() const      { return _trackOffset;   }
setTrack(int val)157       void setTrack(int val)       { _track = val;      }
pasteMode()158       bool pasteMode() const       { return _pasteMode; }
setPasteMode(bool v)159       void setPasteMode(bool v)    { _pasteMode = v;    }
160 
161       Location location(bool forceAbsFrac = false) const;
162       void fillLocation(Location&, bool forceAbsFrac = false) const;
163       void setLocation(const Location&); // sets a new reading point, taking into
164                                          // account its type (absolute or relative).
165 
166       void addBeam(Beam* s);
findBeam(int id)167       Beam* findBeam(int id) const          { return _beams.value(id);   }
168 
169       void addTuplet(Tuplet* s);
findTuplet(int id)170       Tuplet* findTuplet(int id) const      { return _tuplets.value(id); }
tuplets()171       QHash<int, Tuplet*>& tuplets()        { return _tuplets; }
172 
setLastMeasure(Measure * m)173       void setLastMeasure(Measure* m)       { _lastMeasure = m;    }
lastMeasure()174       Measure* lastMeasure() const          { return _lastMeasure; }
setCurrentMeasure(Measure * m)175       void setCurrentMeasure(Measure* m)    { _curMeasure = m; }
currentMeasure()176       Measure* currentMeasure() const       { return _curMeasure; }
setCurrentMeasureIndex(int idx)177       void setCurrentMeasureIndex(int idx)  { _curMeasureIdx = idx;  }
currentMeasureIndex()178       int currentMeasureIndex() const       { return _curMeasureIdx; }
179 
180       void removeSpanner(const Spanner*);
181       void addSpanner(int id, Spanner*);
182       Spanner* findSpanner(int id);
183 
184       int spannerId(const Spanner*);      // returns spanner id, allocates new one if none exists
185 
addSpannerValues(const SpannerValues & sv)186       void addSpannerValues(const SpannerValues& sv) { _spannerValues.append(sv); }
187       const SpannerValues* spannerValues(int id) const;
188 
addConnectorInfoLater(std::unique_ptr<ConnectorInfoReader> c)189       void addConnectorInfoLater(std::unique_ptr<ConnectorInfoReader> c) { _pendingConnectors.push_back(std::move(c)); } // add connector info to be checked after calling checkConnectors()
190       void checkConnectors();
191       void reconnectBrokenConnectors();
192 
staffType()193       QList<StaffType>& staffType()     { return _staffTypes; }
transpose()194       Interval transpose() const        { return _transpose; }
setTransposeChromatic(int v)195       void setTransposeChromatic(int v) { _transpose.chromatic = v; }
setTransposeDiatonic(int v)196       void setTransposeDiatonic(int v)  { _transpose.diatonic = v; }
197 
198       LinkedElements* getLink(bool masterScore, const Location& l, int localIndexDiff);
199       void addLink(Staff* staff, LinkedElements* link);
linkIds()200       QMap<int, LinkedElements*>& linkIds() { return _elinks;     }
tracks()201       QMultiMap<int, int>& tracks()         { return _tracks;     }
202 
203       void checkTuplets();
204       Tid addUserTextStyle(const QString& name);
205       Tid lookupUserTextStyle(const QString& name) const;
clearUserTextStyles()206       void clearUserTextStyles() { userTextStyles.clear(); }
207 
fixOffsets()208       QList<std::pair<Element*, QPointF>>& fixOffsets() { return  _fixOffsets; }
209 
210       // for reading old files (< 3.01)
staffLinkedElements()211       QMap<int, QList<QPair<LinkedElements*, Location>>>& staffLinkedElements() { return _staffLinkedElements; }
setOffsetLines(qint64 val)212       void setOffsetLines(qint64 val) { _offsetLines = val; }
213       };
214 
215 //---------------------------------------------------------
216 //   XmlWriter
217 //---------------------------------------------------------
218 
219 class XmlWriter : public QTextStream {
220       static const int BS = 2048;
221 
222       Score* _score;
223       QList<QString> stack;
224       SelectionFilter _filter;
225 
226       Fraction _curTick    { 0, 1 };     // used to optimize output
227       Fraction _tickDiff   { 0, 1 };
228       int _curTrack        { -1 };
229       int _trackDiff       { 0 };       // saved track is curTrack-trackDiff
230 
231       bool _clipboardmode  { false };   // used to modify write() behaviour
232       bool _excerptmode    { false };   // true when writing a part
233       bool _writeOmr       { true };    // false if writing into *.msc file
234       bool _writeTrack     { false };
235       bool _writePosition  { false };
236 
237       LinksIndexer _linksIndexer;
238       QMap<int, int> _lidLocalIndices;
239 
240       std::vector<std::pair<const ScoreElement*, QString>> _elements;
241       bool _recordElements = false;
242 
243       void putLevel();
244 
245    public:
246       XmlWriter(Score*);
247       XmlWriter(Score* s, QIODevice* dev);
248 
curTick()249       Fraction curTick() const            { return _curTick; }
setCurTick(const Fraction & v)250       void setCurTick(const Fraction& v)  { _curTick   = v; }
incCurTick(const Fraction & v)251       void incCurTick(const Fraction& v)  { _curTick += v; }
252 
curTrack()253       int curTrack() const                { return _curTrack; }
setCurTrack(int v)254       void setCurTrack(int v)             { _curTrack  = v; }
255 
tickDiff()256       Fraction tickDiff() const           { return _tickDiff; }
setTickDiff(const Fraction & v)257       void setTickDiff(const Fraction& v) { _tickDiff  = v; }
258 
trackDiff()259       int trackDiff() const               { return _trackDiff; }
setTrackDiff(int v)260       void setTrackDiff(int v)            { _trackDiff = v; }
261 
clipboardmode()262       bool clipboardmode() const          { return _clipboardmode; }
excerptmode()263       bool excerptmode() const            { return _excerptmode;   }
writeOmr()264       bool writeOmr() const               { return _writeOmr;   }
writeTrack()265       bool writeTrack() const             { return _writeTrack;    }
writePosition()266       bool writePosition() const          { return _writePosition; }
267 
setClipboardmode(bool v)268       void setClipboardmode(bool v)       { _clipboardmode = v; }
setExcerptmode(bool v)269       void setExcerptmode(bool v)         { _excerptmode = v;   }
setWriteOmr(bool v)270       void setWriteOmr(bool v)            { _writeOmr = v;      }
setWriteTrack(bool v)271       void setWriteTrack(bool v)          { _writeTrack= v;     }
setWritePosition(bool v)272       void setWritePosition(bool v)       { _writePosition = v; }
273 
274       int assignLocalIndex(const Location& mainElementLocation);
setLidLocalIndex(int lid,int localIndex)275       void setLidLocalIndex(int lid, int localIndex) { _lidLocalIndices.insert(lid, localIndex); }
lidLocalIndex(int lid)276       int lidLocalIndex(int lid) const { return _lidLocalIndices[lid]; }
277 
elements()278       const std::vector<std::pair<const ScoreElement*, QString>>& elements() const { return _elements; }
setRecordElements(bool record)279       void setRecordElements(bool record) { _recordElements = record; }
280 
sTag(const char * name,Spatium sp)281       void sTag(const char* name, Spatium sp) { XmlWriter::tag(name, QVariant(sp.val())); }
282       void pTag(const char* name, PlaceText);
283 
284       void header();
285 
286       void stag(const QString&);
287       void etag();
288 
289       void stag(const ScoreElement* se, const QString& attributes = QString());
290       void stag(const QString& name, const ScoreElement* se, const QString& attributes = QString());
291 
292       void tagE(const QString&);
293       void tagE(const char* format, ...);
294       void ntag(const char* name);
295       void netag(const char* name);
296 
297       void tag(Pid id, void* data, void* defaultVal);
298       void tag(Pid id, QVariant data, QVariant defaultData = QVariant());
299       void tag(const char* name, QVariant data, QVariant defaultData = QVariant());
300       void tag(const QString&, QVariant data);
tag(const char * name,const char * s)301       void tag(const char* name, const char* s)    { tag(name, QVariant(s)); }
tag(const char * name,const QString & s)302       void tag(const char* name, const QString& s) { tag(name, QVariant(s)); }
303       void tag(const char* name, const QWidget*);
304 
305       void comment(const QString&);
306 
307       void writeXml(const QString&, QString s);
308       void dump(int len, const unsigned char* p);
309 
setFilter(SelectionFilter f)310       void setFilter(SelectionFilter f) { _filter = f; }
311       bool canWrite(const Element*) const;
312       bool canWriteVoice(int track) const;
313 
314       static QString xmlString(const QString&);
315       static QString xmlString(ushort c);
316       };
317 
318 extern PlaceText readPlacement(XmlReader&);
319 }     // namespace Ms
320 #endif
321 
322