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