2012-05-26 14:26:10 +02:00
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2004-2011 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
# ifndef __XML_H__
# define __XML_H__
2020-02-15 12:51:50 +01:00
# include <QMultiMap>
2018-05-26 20:01:06 +02:00
# include "connector.h"
2014-04-30 10:08:38 +02:00
# include "stafftype.h"
2014-05-05 15:38:40 +02:00
# include "interval.h"
2014-07-23 16:08:46 +02:00
# include "element.h"
# include "select.h"
2012-05-26 14:26:10 +02:00
2013-05-13 18:49:17 +02:00
namespace Ms {
2014-06-24 14:45:50 +02:00
enum class PlaceText : char ;
2014-07-25 17:13:27 +02:00
enum class ClefType : signed char ;
2013-01-21 20:21:41 +01:00
class Spanner ;
class Beam ;
class Tuplet ;
2014-02-26 19:06:42 +01:00
class Measure ;
2016-03-30 22:33:04 +02:00
class LinkedElements ;
2013-01-21 20:21:41 +01:00
2013-10-13 13:06:32 +02:00
//---------------------------------------------------------
// SpannerValues
//---------------------------------------------------------
struct SpannerValues {
int spannerId ;
2019-01-30 15:13:54 +01:00
Fraction tick2 ;
2013-10-13 13:06:32 +02:00
int track2 ;
} ;
2018-06-11 14:16:16 +02:00
//---------------------------------------------------------
2018-08-01 11:46:07 +02:00
// TextStyleMap
2018-06-11 14:16:16 +02:00
//---------------------------------------------------------
2018-08-01 11:46:07 +02:00
struct TextStyleMap {
2018-06-11 14:16:16 +02:00
QString name ;
2018-08-01 11:46:07 +02:00
Tid ss ;
2018-06-11 14:16:16 +02:00
} ;
2018-06-17 07:06:25 +02:00
//---------------------------------------------------------
// LinksIndexer
//---------------------------------------------------------
class LinksIndexer {
int _lastLocalIndex { - 1 } ;
Location _lastLinkedElementLoc { Location : : absolute ( ) } ;
public :
int assignLocalIndex ( const Location & mainElementInfo ) ;
} ;
2013-01-11 18:10:18 +01:00
//---------------------------------------------------------
// XmlReader
//---------------------------------------------------------
2016-03-05 10:29:38 +01:00
class XmlReader : public QXmlStreamReader {
2013-01-11 18:10:18 +01:00
QString docName ; // used for error reporting
2018-12-12 17:28:59 +01:00
// For readahead possibility.
2020-02-27 22:47:32 +01:00
// If needed, must be explicitly set by setDevice.
QIODevice * _readDevice = nullptr ;
2018-12-12 17:28:59 +01:00
2013-01-21 20:21:41 +01:00
// Score read context (for read optimizations):
2019-01-30 15:13:54 +01:00
Fraction _tick { Fraction ( 0 , 1 ) } ;
Fraction _tickOffset { Fraction ( 0 , 1 ) } ;
2019-02-18 09:58:34 +01:00
int _intTick { 0 } ;
2014-07-30 12:34:56 +02:00
int _track { 0 } ;
2014-11-06 10:44:57 +01:00
int _trackOffset { 0 } ;
2014-07-30 12:34:56 +02:00
bool _pasteMode { false } ; // modifies read behaviour on paste operation
2017-02-16 11:17:52 +01:00
Measure * _lastMeasure { 0 } ;
2019-01-30 15:13:54 +01:00
Measure * _curMeasure { 0 } ;
int _curMeasureIdx { 0 } ;
2014-12-17 10:45:52 +01:00
QHash < int , Beam * > _beams ;
QHash < int , Tuplet * > _tuplets ;
2016-04-06 15:28:10 +02:00
2013-10-13 13:06:32 +02:00
QList < SpannerValues > _spannerValues ;
2014-07-21 13:24:21 +02:00
QList < std : : pair < int , Spanner * > > _spanner ;
2014-04-30 10:08:38 +02:00
QList < StaffType > _staffTypes ;
2018-12-04 14:24:45 +01:00
QList < std : : pair < Element * , QPointF > > _fixOffsets ;
2016-04-06 15:28:10 +02:00
2018-12-02 00:38:46 +01:00
std : : vector < std : : unique_ptr < ConnectorInfoReader > > _connectors ;
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.
2018-05-26 20:01:06 +02:00
2014-02-17 16:28:09 +01:00
void htmlToString ( int level , QString * ) ;
2014-05-05 15:38:40 +02:00
Interval _transpose ;
2018-06-17 07:06:25 +02:00
QMap < int , LinkedElements * > _elinks ; // for reading old files (< 3.01)
QMap < int , QList < QPair < LinkedElements * , Location > > > _staffLinkedElements ; // one list per staff
LinksIndexer _linksIndexer ;
2016-09-19 13:59:57 +02:00
QMultiMap < int , int > _tracks ;
2013-01-21 20:21:41 +01:00
2018-08-01 11:46:07 +02:00
QList < TextStyleMap > userTextStyles ;
2018-06-11 14:16:16 +02:00
2018-12-02 00:38:46 +01:00
void addConnectorInfo ( std : : unique_ptr < ConnectorInfoReader > ) ;
void removeConnector ( const ConnectorInfoReader * ) ; // Removes the whole ConnectorInfo chain from the connectors list.
2013-01-11 18:10:18 +01:00
public :
2018-02-21 13:30:07 +01:00
XmlReader ( QFile * f ) : QXmlStreamReader ( f ) , docName ( f - > fileName ( ) ) { }
XmlReader ( const QByteArray & d , const QString & st = QString ( ) ) : QXmlStreamReader ( d ) , docName ( st ) { }
XmlReader ( QIODevice * d , const QString & st = QString ( ) ) : QXmlStreamReader ( d ) , docName ( st ) { }
XmlReader ( const QString & d , const QString & st = QString ( ) ) : QXmlStreamReader ( d ) , docName ( st ) { }
2018-05-26 20:01:06 +02:00
XmlReader ( const XmlReader & ) = delete ;
2018-12-12 17:28:59 +01:00
XmlReader & operator = ( const XmlReader & ) = delete ;
2018-05-26 20:01:06 +02:00
~ XmlReader ( ) ;
2013-01-11 18:10:18 +01:00
2020-03-19 14:26:42 +01:00
bool hasAccidental { false } ; // used for userAccidental backward compatibility
2015-02-10 15:05:33 +01:00
void unknown ( ) ;
2013-01-11 18:10:18 +01:00
// attribute helper routines:
QString attribute ( const char * s ) const { return attributes ( ) . value ( s ) . toString ( ) ; }
QString attribute ( const char * s , const QString & ) const ;
int intAttribute ( const char * s ) const ;
int intAttribute ( const char * s , int _default ) const ;
double doubleAttribute ( const char * s ) const ;
double doubleAttribute ( const char * s , double _default ) const ;
bool hasAttribute ( const char * s ) const ;
// helper routines based on readElementText():
2018-12-21 14:56:00 +01:00
int readInt ( ) { return readElementText ( ) . toInt ( ) ; }
int readInt ( bool * ok ) { return readElementText ( ) . toInt ( ok ) ; }
int readIntHex ( ) { return readElementText ( ) . toInt ( 0 , 16 ) ; }
double readDouble ( ) { return readElementText ( ) . toDouble ( ) ; }
qlonglong readLongLong ( ) { return readElementText ( ) . toLongLong ( ) ; }
2019-02-18 09:58:34 +01:00
2015-01-15 14:50:50 +01:00
double readDouble ( double min , double max ) ;
2015-04-08 11:58:10 +02:00
bool readBool ( ) ;
2013-01-11 18:10:18 +01:00
QPointF readPoint ( ) ;
QSizeF readSize ( ) ;
QRectF readRect ( ) ;
QColor readColor ( ) ;
Fraction readFraction ( ) ;
2014-02-17 16:28:09 +01:00
QString readXml ( ) ;
2013-01-11 18:10:18 +01:00
void setDocName ( const QString & s ) { docName = s ; }
2014-02-17 16:28:09 +01:00
QString getDocName ( ) const { return docName ; }
2013-01-21 20:21:41 +01:00
2019-01-30 15:13:54 +01:00
Fraction tick ( ) const { return _tick + _tickOffset ; }
Fraction rtick ( ) const ;
void setTick ( const Fraction & f ) ;
void incTick ( const Fraction & f ) ;
void setTickOffset ( const Fraction & val ) { _tickOffset = val ; }
2014-11-06 10:44:57 +01:00
int track ( ) const { return _track + _trackOffset ; }
void setTrackOffset ( int val ) { _trackOffset = val ; }
int trackOffset ( ) const { return _trackOffset ; }
void setTrack ( int val ) { _track = val ; }
bool pasteMode ( ) const { return _pasteMode ; }
void setPasteMode ( bool v ) { _pasteMode = v ; }
2014-07-30 12:34:56 +02:00
2018-08-14 23:15:43 +02:00
Location location ( bool forceAbsFrac = false ) const ;
void fillLocation ( Location & , bool forceAbsFrac = false ) const ;
void setLocation ( const Location & ) ; // sets a new reading point, taking into
// account its type (absolute or relative).
2014-12-17 10:45:52 +01:00
void addBeam ( Beam * s ) ;
2019-01-30 15:13:54 +01:00
Beam * findBeam ( int id ) const { return _beams . value ( id ) ; }
2014-12-17 10:45:52 +01:00
2013-01-24 09:31:41 +01:00
void addTuplet ( Tuplet * s ) ;
2019-01-30 15:13:54 +01:00
Tuplet * findTuplet ( int id ) const { return _tuplets . value ( id ) ; }
QHash < int , Tuplet * > & tuplets ( ) { return _tuplets ; }
2013-01-21 20:21:41 +01:00
2019-01-30 15:13:54 +01:00
void setLastMeasure ( Measure * m ) { _lastMeasure = m ; }
Measure * lastMeasure ( ) const { return _lastMeasure ; }
void setCurrentMeasure ( Measure * m ) { _curMeasure = m ; }
Measure * currentMeasure ( ) const { return _curMeasure ; }
void setCurrentMeasureIndex ( int idx ) { _curMeasureIdx = idx ; }
int currentMeasureIndex ( ) const { return _curMeasureIdx ; }
2014-02-26 19:06:42 +01:00
2014-07-21 13:24:21 +02:00
void removeSpanner ( const Spanner * ) ;
void addSpanner ( int id , Spanner * ) ;
2014-06-24 14:45:50 +02:00
Spanner * findSpanner ( int id ) ;
2018-05-26 20:01:06 +02:00
2014-07-21 13:24:21 +02:00
int spannerId ( const Spanner * ) ; // returns spanner id, allocates new one if none exists
2014-06-24 14:45:50 +02:00
2013-10-13 13:06:32 +02:00
void addSpannerValues ( const SpannerValues & sv ) { _spannerValues . append ( sv ) ; }
2015-03-03 15:45:25 +01:00
const SpannerValues * spannerValues ( int id ) const ;
2018-05-26 20:01:06 +02:00
2018-12-02 00:38:46 +01:00
void addConnectorInfoLater ( std : : unique_ptr < ConnectorInfoReader > c ) { _pendingConnectors . push_back ( std : : move ( c ) ) ; } // add connector info to be checked after calling checkConnectors()
2018-05-26 20:01:06 +02:00
void checkConnectors ( ) ;
void reconnectBrokenConnectors ( ) ;
2016-04-06 15:28:10 +02:00
QList < StaffType > & staffType ( ) { return _staffTypes ; }
Interval transpose ( ) const { return _transpose ; }
2014-05-05 15:38:40 +02:00
void setTransposeChromatic ( int v ) { _transpose . chromatic = v ; }
2016-04-06 15:28:10 +02:00
void setTransposeDiatonic ( int v ) { _transpose . diatonic = v ; }
2014-07-25 17:13:27 +02:00
2018-06-17 07:06:25 +02:00
LinkedElements * getLink ( bool masterScore , const Location & l , int localIndexDiff ) ;
void addLink ( Staff * staff , LinkedElements * link ) ;
2016-03-30 22:33:04 +02:00
QMap < int , LinkedElements * > & linkIds ( ) { return _elinks ; }
2016-09-19 13:59:57 +02:00
QMultiMap < int , int > & tracks ( ) { return _tracks ; }
2016-09-26 10:15:20 +02:00
void checkTuplets ( ) ;
2018-08-01 11:46:07 +02:00
Tid addUserTextStyle ( const QString & name ) ;
Tid lookupUserTextStyle ( const QString & name ) ;
2018-12-04 14:24:45 +01:00
2020-02-27 22:47:32 +01:00
// Ownership on read device is NOT transferred to XmlReader.
void setDevice ( QIODevice * dev ) { if ( ! dev - > isSequential ( ) ) _readDevice = dev ; }
QIODevice * getDevice ( ) { return _readDevice ; }
2018-12-12 17:28:59 +01:00
2018-12-04 14:24:45 +01:00
QList < std : : pair < Element * , QPointF > > & fixOffsets ( ) { return _fixOffsets ; }
2013-01-11 18:10:18 +01:00
} ;
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2016-11-19 11:51:21 +01:00
// XmlWriter
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2016-11-19 11:51:21 +01:00
class XmlWriter : public QTextStream {
2012-05-26 14:26:10 +02:00
static const int BS = 2048 ;
2016-11-19 10:31:14 +01:00
Score * _score ;
2012-05-26 14:26:10 +02:00
QList < QString > stack ;
2014-07-23 16:08:46 +02:00
SelectionFilter _filter ;
2012-05-26 14:26:10 +02:00
2019-01-30 15:13:54 +01:00
Fraction _curTick { 0 , 1 } ; // used to optimize output
Fraction _tickDiff { 0 , 1 } ;
int _curTrack { - 1 } ;
int _trackDiff { 0 } ; // saved track is curTrack-trackDiff
2014-03-14 11:30:19 +01:00
2019-01-30 15:13:54 +01:00
bool _clipboardmode { false } ; // used to modify write() behaviour
bool _excerptmode { false } ; // true when writing a part
bool _writeOmr { true } ; // false if writing into *.msc file
bool _writeTrack { false } ;
bool _writePosition { false } ;
2014-03-14 11:30:19 +01:00
2018-06-17 07:06:25 +02:00
LinksIndexer _linksIndexer ;
QMap < int , int > _lidLocalIndices ;
2018-09-26 12:20:00 +02:00
std : : vector < std : : pair < const ScoreElement * , QString > > _elements ;
bool _recordElements = false ;
2016-11-19 10:31:14 +01:00
void putLevel ( ) ;
public :
2016-11-19 11:51:21 +01:00
XmlWriter ( Score * ) ;
XmlWriter ( Score * s , QIODevice * dev ) ;
2016-11-19 10:31:14 +01:00
2019-01-30 15:13:54 +01:00
Fraction curTick ( ) const { return _curTick ; }
void setCurTick ( const Fraction & v ) { _curTick = v ; }
void incCurTick ( const Fraction & v ) { _curTick + = v ; }
int curTrack ( ) const { return _curTrack ; }
void setCurTrack ( int v ) { _curTrack = v ; }
Fraction tickDiff ( ) const { return _tickDiff ; }
void setTickDiff ( const Fraction & v ) { _tickDiff = v ; }
int trackDiff ( ) const { return _trackDiff ; }
void setTrackDiff ( int v ) { _trackDiff = v ; }
bool clipboardmode ( ) const { return _clipboardmode ; }
bool excerptmode ( ) const { return _excerptmode ; }
bool writeOmr ( ) const { return _writeOmr ; }
bool writeTrack ( ) const { return _writeTrack ; }
bool writePosition ( ) const { return _writePosition ; }
void setClipboardmode ( bool v ) { _clipboardmode = v ; }
void setExcerptmode ( bool v ) { _excerptmode = v ; }
void setWriteOmr ( bool v ) { _writeOmr = v ; }
void setWriteTrack ( bool v ) { _writeTrack = v ; }
void setWritePosition ( bool v ) { _writePosition = v ; }
2014-07-21 13:24:21 +02:00
2018-06-17 07:06:25 +02:00
int assignLocalIndex ( const Location & mainElementLocation ) ;
void setLidLocalIndex ( int lid , int localIndex ) { _lidLocalIndices . insert ( lid , localIndex ) ; }
2019-11-03 13:08:46 +01:00
int lidLocalIndex ( int lid ) const { Q_ASSERT ( _lidLocalIndices . contains ( lid ) ) ; return _lidLocalIndices [ lid ] ; }
2018-06-17 07:06:25 +02:00
2018-09-26 12:20:00 +02:00
const std : : vector < std : : pair < const ScoreElement * , QString > > & elements ( ) const { return _elements ; }
void setRecordElements ( bool record ) { _recordElements = record ; }
2016-11-19 11:51:21 +01:00
void sTag ( const char * name , Spatium sp ) { XmlWriter : : tag ( name , QVariant ( sp . val ( ) ) ) ; }
2012-10-30 09:06:24 +01:00
void pTag ( const char * name , PlaceText ) ;
2012-05-26 14:26:10 +02:00
void header ( ) ;
void stag ( const QString & ) ;
void etag ( ) ;
2018-09-26 12:20:00 +02:00
void stag ( const ScoreElement * se , const QString & attributes = QString ( ) ) ;
void stag ( const QString & name , const ScoreElement * se , const QString & attributes = QString ( ) ) ;
2012-05-26 14:26:10 +02:00
void tagE ( const QString & ) ;
void tagE ( const char * format , . . . ) ;
void ntag ( const char * name ) ;
void netag ( const char * name ) ;
2018-03-27 15:36:00 +02:00
void tag ( Pid id , void * data , void * defaultVal ) ;
void tag ( Pid id , QVariant data , QVariant defaultData = QVariant ( ) ) ;
2012-05-26 14:26:10 +02:00
void tag ( const char * name , QVariant data , QVariant defaultData = QVariant ( ) ) ;
void tag ( const QString & , QVariant data ) ;
void tag ( const char * name , const char * s ) { tag ( name , QVariant ( s ) ) ; }
void tag ( const char * name , const QString & s ) { tag ( name , QVariant ( s ) ) ; }
void tag ( const char * name , const QWidget * ) ;
2018-05-23 00:32:33 +02:00
void comment ( const QString & ) ;
2014-03-25 16:55:51 +01:00
void writeXml ( const QString & , QString s ) ;
2012-05-26 14:26:10 +02:00
void dump ( int len , const unsigned char * p ) ;
2014-07-23 16:08:46 +02:00
void setFilter ( SelectionFilter f ) { _filter = f ; }
bool canWrite ( const Element * ) const ;
2014-08-07 00:30:50 +02:00
bool canWriteVoice ( int track ) const ;
2014-07-23 16:08:46 +02:00
2012-05-26 14:26:10 +02:00
static QString xmlString ( const QString & ) ;
2014-11-27 11:31:42 +01:00
static QString xmlString ( ushort c ) ;
2012-05-26 14:26:10 +02:00
} ;
2013-01-11 18:10:18 +01:00
extern PlaceText readPlacement ( XmlReader & ) ;
2013-05-13 18:49:17 +02:00
} // namespace Ms
2012-05-26 14:26:10 +02:00
# endif