added XmlStreamWriter (hidden Qt QTextStream)

This commit is contained in:
Igor Korsukov 2022-05-13 19:41:28 +03:00
parent c77bf9c2f9
commit 0dd1451e48
18 changed files with 359 additions and 344 deletions

View file

@ -21,6 +21,9 @@
*/
#include "figuredbass.h"
#include <QFile>
#include "draw/fontmetrics.h"
#include "rw/xml.h"
#include "score.h"

View file

@ -22,6 +22,8 @@
#include "instrtemplate.h"
#include <QFile>
#include "translation.h"
#include "containers.h"
#include "style/style.h"

View file

@ -620,12 +620,16 @@ QString propertyToString(Pid id, const PropertyValue& value, bool mscx)
switch (propertyType(id)) {
case P_TYPE::DURATION_TYPE_WITH_DOTS:
ASSERT_X("unknown: TDURATION");
break;
case P_TYPE::TEMPO:
ASSERT_X("unknown: TEMPO");
break;
case P_TYPE::GROUPS:
ASSERT_X("unknown: GROUPS");
break;
case P_TYPE::INT_VEC:
ASSERT_X("unknown: INT_VEC");
break;
default: {
break;
}

View file

@ -257,6 +257,7 @@ public:
bool isValid() const;
P_TYPE type() const;
bool isEnum() const { return m_data ? m_data->isEnum() : false; }
template<typename T>
T value() const

View file

@ -2914,7 +2914,7 @@ Score::FileError Read114::read114(MasterScore* masterScore, XmlReader& e, ReadCo
}
}
if (e.error() != QXmlStreamReader::NoError) {
if (e.error() != XmlStreamReader::NoError) {
LOGD("%lld %lld: %s ", e.lineNumber(), e.columnNumber(), qPrintable(e.errorString()));
return Score::FileError::FILE_BAD_FORMAT;
}

View file

@ -3342,7 +3342,7 @@ bool Read206::readScore206(Score* score, XmlReader& e, ReadContext& ctx)
e.unknown();
}
}
if (e.error() != QXmlStreamReader::NoError) {
if (e.error() != XmlStreamReader::NoError) {
LOGD("%s: xml read error at line %lld col %lld: %s",
qPrintable(e.getDocName()), e.lineNumber(), e.columnNumber(),
e.name().toUtf8().data());

View file

@ -225,11 +225,11 @@ bool Read302::readScore302(Ms::Score* score, XmlReader& e, ReadContext& ctx)
}
}
e.context()->reconnectBrokenConnectors();
if (e.error() != QXmlStreamReader::NoError) {
if (e.error() != XmlStreamReader::NoError) {
LOGD("%s: xml read error at line %lld col %lld: %s",
qPrintable(e.getDocName()), e.lineNumber(), e.columnNumber(),
e.name().toUtf8().data());
if (e.error() == QXmlStreamReader::CustomError) {
if (e.error() == XmlStreamReader::CustomError) {
MScore::lastError = e.errorString();
} else {
MScore::lastError = QObject::tr("XML read error at line %1, column %2: %3").arg(e.lineNumber()).arg(e.columnNumber()).arg(
@ -277,7 +277,7 @@ Score::FileError Read302::read302(Ms::MasterScore* masterScore, XmlReader& e, Re
masterScore->setMscoreRevision(e.readIntHex());
} else if (tag == "Score") {
if (!readScore302(masterScore, e, ctx)) {
if (e.error() == QXmlStreamReader::CustomError) {
if (e.error() == XmlStreamReader::CustomError) {
return Score::FileError::FILE_CRITICALLY_CORRUPTED;
}
return Score::FileError::FILE_BAD_FORMAT;

View file

@ -221,11 +221,11 @@ bool Read400::readScore400(Ms::Score* score, XmlReader& e, ReadContext& ctx)
}
}
ctx.reconnectBrokenConnectors();
if (e.error() != QXmlStreamReader::NoError) {
if (e.error() != XmlStreamReader::NoError) {
LOGD("%s: xml read error at line %lld col %lld: %s",
qPrintable(e.getDocName()), e.lineNumber(), e.columnNumber(),
e.name().toUtf8().data());
if (e.error() == QXmlStreamReader::CustomError) {
if (e.error() == XmlStreamReader::CustomError) {
MScore::lastError = e.errorString();
} else {
MScore::lastError = QObject::tr("XML read error at line %1, column %2: %3").arg(e.lineNumber()).arg(e.columnNumber()).arg(

View file

@ -210,7 +210,7 @@ Err ScoreReader::doRead(MasterScore* score, XmlReader& e, ReadContext& ctx)
score->setMscoreRevision(e.readIntHex());
} else if (tag == "Score") {
if (!Read400::readScore400(score, e, ctx)) {
if (e.error() == QXmlStreamReader::CustomError) {
if (e.error() == XmlStreamReader::CustomError) {
return Err::FileCriticalCorrupted;
}
return Err::FileBadFormat;

View file

@ -40,13 +40,11 @@ namespace Ms {
XmlWriter::XmlWriter()
{
setCodec("UTF-8");
}
XmlWriter::XmlWriter(QIODevice* device)
: QTextStream(device)
: XmlStreamWriter(device)
{
setCodec("UTF-8");
}
XmlWriter::~XmlWriter()
@ -56,27 +54,6 @@ XmlWriter::~XmlWriter()
}
}
//---------------------------------------------------------
// putLevel
//---------------------------------------------------------
void XmlWriter::putLevel()
{
size_t level = stack.size();
for (size_t i = 0; i < level * 2; ++i) {
*this << ' ';
}
}
//---------------------------------------------------------
// header
//---------------------------------------------------------
void XmlWriter::writeHeader()
{
*this << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
}
//---------------------------------------------------------
// stag
// <mops attribute="value">
@ -84,9 +61,7 @@ void XmlWriter::writeHeader()
void XmlWriter::startObject(const QString& s)
{
putLevel();
*this << '<' << s << '>' << Qt::endl;
stack.push_back(s.split(' ')[0]);
XmlStreamWriter::writeStartElement(s);
}
//---------------------------------------------------------
@ -106,13 +81,7 @@ void XmlWriter::startObject(const EngravingObject* se, const QString& attributes
void XmlWriter::startObject(const QString& name, const EngravingObject* se, const QString& attributes)
{
putLevel();
*this << '<' << name;
if (!attributes.isEmpty()) {
*this << ' ' << attributes;
}
*this << '>' << Qt::endl;
stack.push_back(name);
XmlStreamWriter::writeStartElement(name, attributes);
if (_recordElements) {
_elements.emplace_back(se, name);
@ -126,26 +95,7 @@ void XmlWriter::startObject(const QString& name, const EngravingObject* se, cons
void XmlWriter::endObject()
{
putLevel();
*this << "</" << mu::takeLast(stack) << '>' << Qt::endl;
}
//---------------------------------------------------------
// tagE
// <mops attribute="value"/>
//---------------------------------------------------------
void XmlWriter::tagE(const char* format, ...)
{
va_list args;
va_start(args, format);
putLevel();
*this << '<';
char buffer[BS];
vsnprintf(buffer, BS, format, args);
*this << buffer;
va_end(args);
*this << "/>" << Qt::endl;
XmlStreamWriter::writeEndElement();
}
//---------------------------------------------------------
@ -154,29 +104,7 @@ void XmlWriter::tagE(const char* format, ...)
void XmlWriter::tagE(const QString& s)
{
putLevel();
*this << '<' << s << "/>\n";
}
//---------------------------------------------------------
// ntag
// <mops> without newline
//---------------------------------------------------------
void XmlWriter::ntag(const char* name)
{
putLevel();
*this << "<" << name << ">";
}
//---------------------------------------------------------
// netag
// </mops> without indentation
//---------------------------------------------------------
void XmlWriter::netag(const char* s)
{
*this << "</" << s << '>' << Qt::endl;
XmlStreamWriter::writeElement(s);
}
//---------------------------------------------------------
@ -220,38 +148,33 @@ void XmlWriter::tag(Pid id, const PropertyValue& val, const PropertyValue& def)
}
}
void XmlWriter::tagProperty(const char* name, P_TYPE type, const PropertyValue& data)
void XmlWriter::tagProperty(const QString& name, const PropertyValue& val, const PropertyValue& def)
{
QString ename(QString(name).split(' ')[0]);
if (val == def) {
return;
}
tagProperty(name, val.type(), val);
}
void XmlWriter::tagProperty(const QString& name, P_TYPE type, const PropertyValue& data)
{
switch (type) {
case P_TYPE::UNDEFINED:
UNREACHABLE;
break;
// base
case P_TYPE::BOOL:
putLevel();
*this << "<" << name << ">";
*this << int(data.value<bool>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, int(data.value<bool>()));
break;
case P_TYPE::INT:
putLevel();
*this << "<" << name << ">";
*this << data.value<int>();
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, data.value<int>());
break;
case P_TYPE::REAL:
putLevel();
*this << "<" << name << ">";
*this << data.value<qreal>();
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, data.value<qreal>());
break;
case P_TYPE::STRING:
putLevel();
*this << "<" << name << ">";
*this << xmlString(data.value<QString>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, xmlString(data.value<QString>()));
break;
// geometry
case P_TYPE::POINT: {
@ -260,9 +183,8 @@ void XmlWriter::tagProperty(const char* name, P_TYPE type, const PropertyValue&
}
break;
case P_TYPE::SIZE: {
putLevel();
SizeF s = data.value<SizeF>();
*this << QString("<%1 w=\"%2\" h=\"%3\"/>\n").arg(name).arg(s.width()).arg(s.height());
XmlStreamWriter::writeElement(QString("%1 w=\"%2\" h=\"%3\"").arg(name).arg(s.width()).arg(s.height()));
}
break;
case P_TYPE::DRAW_PATH:
@ -272,92 +194,54 @@ void XmlWriter::tagProperty(const char* name, P_TYPE type, const PropertyValue&
UNREACHABLE; //! TODO
break;
case P_TYPE::SPATIUM:
putLevel();
*this << "<" << name << ">";
*this << data.value<Spatium>().val();
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, data.value<Spatium>().val());
break;
case P_TYPE::MILLIMETRE:
putLevel();
*this << "<" << name << ">";
*this << qreal(data.value<Millimetre>());
*this << "</" << ename << ">\n";
break;
XmlStreamWriter::writeElement(name, data.value<Millimetre>().val());
break;
// draw
case P_TYPE::SYMID: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<SymId>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<SymId>()));
} break;
case P_TYPE::COLOR: {
putLevel();
Color color(data.value<Color>());
*this << QString("<%1 r=\"%2\" g=\"%3\" b=\"%4\" a=\"%5\"/>\n")
.arg(name).arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha());
XmlStreamWriter::writeElement(QString("%1 r=\"%2\" g=\"%3\" b=\"%4\" a=\"%5\"")
.arg(name).arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha()));
}
break;
case P_TYPE::ORNAMENT_STYLE: {
putLevel();
*this << "<" << name << ">";
*this << XmlValue::toXml(data.value<OrnamentStyle>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, XmlValue::toXml(data.value<OrnamentStyle>()));
} break;
case P_TYPE::GLISS_STYLE: {
putLevel();
*this << "<" << name << ">";
*this << XmlValue::toXml(data.value<GlissandoStyle>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, XmlValue::toXml(data.value<GlissandoStyle>()));
} break;
case P_TYPE::ALIGN: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<Align>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<Align>()));
}
break;
case P_TYPE::PLACEMENT_V: {
putLevel();
*this << "<" << name << ">";
*this << XmlValue::toXml(data.value<PlacementV>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, XmlValue::toXml(data.value<PlacementV>()));
}
break;
case P_TYPE::PLACEMENT_H: {
putLevel();
*this << "<" << name << ">";
*this << XmlValue::toXml(data.value<PlacementH>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, XmlValue::toXml(data.value<PlacementH>()));
}
break;
case P_TYPE::TEXT_PLACE: {
putLevel();
*this << "<" << name << ">";
*this << XmlValue::toXml(data.value<TextPlace>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, XmlValue::toXml(data.value<TextPlace>()));
}
break;
case P_TYPE::DIRECTION_V: {
putLevel();
*this << "<" << name << ">";
*this << XmlValue::toXml(data.value<DirectionV>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, XmlValue::toXml(data.value<DirectionV>()));
}
break;
case P_TYPE::DIRECTION_H: {
putLevel();
*this << "<" << name << ">";
*this << XmlValue::toXml(data.value<DirectionH>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, XmlValue::toXml(data.value<DirectionH>()));
}
break;
case P_TYPE::ORIENTATION: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<Orientation>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<Orientation>()));
}
break;
// time
@ -367,106 +251,55 @@ void XmlWriter::tagProperty(const char* name, P_TYPE type, const PropertyValue&
}
break;
case P_TYPE::LAYOUTBREAK_TYPE: {
putLevel();
*this << "<" << name << ">";
*this << XmlValue::toXml(data.value<LayoutBreakType>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, XmlValue::toXml(data.value<LayoutBreakType>()));
} break;
case P_TYPE::VELO_TYPE: {
putLevel();
*this << "<" << name << ">";
*this << XmlValue::toXml(data.value<VeloType>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, XmlValue::toXml(data.value<VeloType>()));
} break;
case P_TYPE::BARLINE_TYPE: {
putLevel();
*this << "<" << name << ">";
*this << XmlValue::toXml(data.value<BarLineType>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, XmlValue::toXml(data.value<BarLineType>()));
} break;
case P_TYPE::NOTEHEAD_TYPE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<NoteHeadType>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<NoteHeadType>()));
} break;
case P_TYPE::NOTEHEAD_SCHEME: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<NoteHeadScheme>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<NoteHeadScheme>()));
} break;
case P_TYPE::NOTEHEAD_GROUP: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<NoteHeadGroup>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<NoteHeadGroup>()));
} break;
case P_TYPE::CLEF_TYPE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<ClefType>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<ClefType>()));
} break;
case P_TYPE::DYNAMIC_TYPE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<DynamicType>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<DynamicType>()));
} break;
case P_TYPE::DYNAMIC_RANGE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<DynamicRange>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<DynamicRange>()));
} break;
case P_TYPE::DYNAMIC_SPEED: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<DynamicSpeed>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<DynamicSpeed>()));
} break;
case P_TYPE::HOOK_TYPE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<HookType>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<HookType>()));
} break;
case P_TYPE::KEY_MODE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<KeyMode>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<KeyMode>()));
} break;
case P_TYPE::TEXT_STYLE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<TextStyleType>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<TextStyleType>()));
} break;
case P_TYPE::CHANGE_METHOD: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<ChangeMethod>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<ChangeMethod>()));
} break;
case P_TYPE::ACCIDENTAL_ROLE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<AccidentalRole>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<AccidentalRole>()));
} break;
case P_TYPE::PLAYTECH_TYPE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<PlayingTechniqueType>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<PlayingTechniqueType>()));
} break;
case P_TYPE::TEMPOCHANGE_TYPE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<TempoChangeType>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, TConv::toXml(data.value<TempoChangeType>()));
} break;
default: {
UNREACHABLE; //! TODO
@ -475,26 +308,23 @@ void XmlWriter::tagProperty(const char* name, P_TYPE type, const PropertyValue&
}
}
void XmlWriter::tag(const char* name, const mu::PointF& p)
void XmlWriter::tag(const QString& name, const mu::PointF& p)
{
putLevel();
*this << QString("<%1 x=\"%2\" y=\"%3\"/>\n").arg(name).arg(p.x()).arg(p.y());
XmlStreamWriter::writeElement(QString("%1 x=\"%2\" y=\"%3\"").arg(name).arg(p.x()).arg(p.y()));
}
void XmlWriter::tag(const char* name, const CustDef& cd)
{
putLevel();
*this << QString("<%1 degree=\"%2\" xAlt=\"%3\" octAlt=\"%4\"/>\n").arg(name).arg(cd.degree).arg(cd.xAlt).arg(cd.octAlt);
XmlStreamWriter::writeElement(QString("%1 degree=\"%2\" xAlt=\"%3\" octAlt=\"%4\"").arg(name).arg(cd.degree).arg(cd.xAlt).arg(cd.octAlt));
}
void XmlWriter::tag(const char* name, const Fraction& v, const Fraction& def)
void XmlWriter::tag(const QString& name, const Fraction& v, const Fraction& def)
{
if (v == def) {
return;
}
putLevel();
*this << QString("<%1>%2/%3</%1>\n").arg(name).arg(v.numerator()).arg(v.denominator());
XmlStreamWriter::writeElement(name, QString("%1/%2").arg(v.numerator()).arg(v.denominator()));
}
//---------------------------------------------------------
@ -511,66 +341,55 @@ void XmlWriter::tag(const char* name, QVariant data, QVariant defaultData)
void XmlWriter::tag(const QString& name, QVariant data)
{
QString ename(name.split(' ')[0]);
putLevel();
switch (data.type()) {
case QVariant::Bool:
case QVariant::Char:
case QVariant::Int:
case QVariant::UInt:
*this << "<" << name << ">";
*this << data.toInt();
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, data.toInt());
break;
case QVariant::LongLong:
*this << "<" << name << ">";
*this << data.toLongLong();
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, data.toLongLong());
break;
case QVariant::Double:
*this << "<" << name << ">";
*this << data.value<double>();
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, data.value<double>());
break;
case QVariant::String:
*this << "<" << name << ">";
*this << xmlString(data.value<QString>());
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, xmlString(data.value<QString>()));
break;
#ifndef NO_QT_SUPPORT
case QVariant::Color:
{
QColor color(data.value<QColor>());
*this << QString("<%1 r=\"%2\" g=\"%3\" b=\"%4\" a=\"%5\"/>\n")
.arg(name).arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha());
}
break;
case QVariant::Rect:
{
const QRect& r(data.value<QRect>());
*this << QString("<%1 x=\"%2\" y=\"%3\" w=\"%4\" h=\"%5\"/>\n").arg(name).arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height());
}
break;
case QVariant::RectF:
{
const QRectF& r(data.value<QRectF>());
*this << QString("<%1 x=\"%2\" y=\"%3\" w=\"%4\" h=\"%5\"/>\n").arg(name).arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height());
}
break;
case QVariant::PointF:
{
const QPointF& p(data.value<QPointF>());
*this << QString("<%1 x=\"%2\" y=\"%3\"/>\n").arg(name).arg(p.x()).arg(p.y());
}
break;
case QVariant::SizeF:
{
const QSizeF& p(data.value<QSizeF>());
*this << QString("<%1 w=\"%2\" h=\"%3\"/>\n").arg(name).arg(p.width()).arg(p.height());
}
break;
// case QVariant::Color:
// {
// QColor color(data.value<QColor>());
// *this << QString("<%1 r=\"%2\" g=\"%3\" b=\"%4\" a=\"%5\"/>\n")
// .arg(name).arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha());
// }
// break;
// case QVariant::Rect:
// {
// const QRect& r(data.value<QRect>());
// *this << QString("<%1 x=\"%2\" y=\"%3\" w=\"%4\" h=\"%5\"/>\n").arg(name).arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height());
// }
// break;
// case QVariant::RectF:
// {
// const QRectF& r(data.value<QRectF>());
// *this << QString("<%1 x=\"%2\" y=\"%3\" w=\"%4\" h=\"%5\"/>\n").arg(name).arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height());
// }
// break;
// case QVariant::PointF:
// {
// const QPointF& p(data.value<QPointF>());
// *this << QString("<%1 x=\"%2\" y=\"%3\"/>\n").arg(name).arg(p.x()).arg(p.y());
// }
// break;
// case QVariant::SizeF:
// {
// const QSizeF& p(data.value<QSizeF>());
// *this << QString("<%1 w=\"%2\" h=\"%3\"/>\n").arg(name).arg(p.width()).arg(p.height());
// }
// break;
#endif
default: {
UNREACHABLE;
@ -585,8 +404,7 @@ void XmlWriter::tag(const QString& name, QVariant data)
void XmlWriter::comment(const QString& text)
{
putLevel();
*this << "<!-- " << text << " -->" << Qt::endl;
XmlStreamWriter::writeComment(text);
}
//---------------------------------------------------------
@ -628,34 +446,6 @@ QString XmlWriter::xmlString(const QString& s)
return escaped;
}
//---------------------------------------------------------
// dump
//---------------------------------------------------------
void XmlWriter::dump(int len, const unsigned char* p)
{
putLevel();
int col = 0;
setFieldWidth(5);
setNumberFlags(numberFlags() | QTextStream::ShowBase);
setIntegerBase(16);
for (int i = 0; i < len; ++i, ++col) {
if (col >= 16) {
setFieldWidth(0);
*this << Qt::endl;
col = 0;
putLevel();
setFieldWidth(5);
}
*this << (p[i] & 0xff);
}
if (col) {
*this << Qt::endl << Qt::dec;
}
setFieldWidth(0);
setIntegerBase(10);
}
//---------------------------------------------------------
// writeXml
// string s is already escaped (& -> "&amp;")
@ -663,17 +453,14 @@ void XmlWriter::dump(int len, const unsigned char* p)
void XmlWriter::writeXml(const QString& name, QString s)
{
QString ename(name.split(' ')[0]);
putLevel();
for (int i = 0; i < s.size(); ++i) {
ushort c = s.at(i).unicode();
if (c < 0x20 && c != 0x09 && c != 0x0A && c != 0x0D) {
s[i] = '?';
}
}
*this << "<" << name << ">";
*this << s;
*this << "</" << ename << ">\n";
XmlStreamWriter::writeElement(name, s);
}
mu::engraving::WriteContext* XmlWriter::context() const

View file

@ -23,9 +23,7 @@
#define MU_ENGRAVING_XMLWRITER_H
#include <map>
#include <QXmlStreamReader>
#include <QTextStream>
#include <QFile>
#include <unordered_map>
@ -37,25 +35,21 @@
#include "libmscore/interval.h"
#include "libmscore/engravingitem.h"
#include "serialization/xmlstreamwriter.h"
namespace mu::engraving {
class WriteContext;
}
namespace Ms {
class XmlWriter : public QTextStream
class XmlWriter : public mu::XmlStreamWriter
{
static const int BS = 2048;
std::list<QString> stack;
std::vector<std::pair<const EngravingObject*, QString> > _elements;
bool _recordElements = false;
mutable mu::engraving::WriteContext* m_context = nullptr;
mutable bool m_selfContext = false;
void putLevel();
public:
XmlWriter();
XmlWriter(QIODevice* dev);
@ -64,8 +58,6 @@ public:
const std::vector<std::pair<const EngravingObject*, QString> >& elements() const { return _elements; }
void setRecordElements(bool record) { _recordElements = record; }
void writeHeader();
void startObject(const QString&);
void endObject();
@ -73,25 +65,23 @@ public:
void startObject(const QString& name, const EngravingObject* se, const QString& attributes = QString());
void tagE(const QString&);
void tagE(const char* format, ...);
void ntag(const char* name);
void netag(const char* name);
void tag(Pid id, const mu::engraving::PropertyValue& data, const mu::engraving::PropertyValue& def = mu::engraving::PropertyValue());
void tagProperty(const char* name, mu::engraving::P_TYPE type, const mu::engraving::PropertyValue& data);
void tagProperty(const QString&, const mu::engraving::PropertyValue& data,
const mu::engraving::PropertyValue& def = mu::engraving::PropertyValue());
void tagProperty(const QString& name, mu::engraving::P_TYPE type, const mu::engraving::PropertyValue& data);
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 mu::PointF& v);
void tag(const char* name, const Fraction& v, const Fraction& def = Fraction());
void tag(const QString& name, const mu::PointF& v);
void tag(const QString& name, const Fraction& v, const Fraction& def = Fraction());
void tag(const char* name, const CustDef& cd);
void comment(const QString&);
void writeXml(const QString&, QString s);
void dump(int len, const unsigned char* p);
mu::engraving::WriteContext* context() const;
void setContext(mu::engraving::WriteContext* context);

View file

@ -357,7 +357,12 @@ void MStyle::save(XmlWriter& xml, bool optimize)
}
xml.tag(st.name(), TConv::toXml(a));
} else {
xml.tag(st.name(), value(idx).toQVariant());
PropertyValue val = value(idx);
//! NOTE for compatibility
if (val.isEnum()) {
val = val.value<int>();
}
xml.tagProperty(st.name(), val);
}
}

View file

@ -912,8 +912,7 @@ ChangeMethod TConv::fromXml(const QString& tag, ChangeMethod def)
QString TConv::toXml(const PitchValue& v)
{
return QString("point time=\"%1\" pitch=\"%2\" vibrato=\"%3\"")
.arg(v.time).arg(v.pitch).arg(v.vibrato);
return QString("point time=\"%1\" pitch=\"%2\" vibrato=\"%3\"").arg(v.time).arg(v.pitch).arg(v.vibrato);
}
QString TConv::toXml(AccidentalRole v)

View file

@ -97,6 +97,8 @@ set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/serialization/xmlstreamreader.cpp
${CMAKE_CURRENT_LIST_DIR}/serialization/xmlstreamreader.h
${CMAKE_CURRENT_LIST_DIR}/serialization/xmlstreamwriter.cpp
${CMAKE_CURRENT_LIST_DIR}/serialization/xmlstreamwriter.h
)
if (NOT NO_GLOBAL_INTERNAL)

View file

@ -64,8 +64,7 @@ public:
explicit XmlStreamReader(QIODevice* device);
explicit XmlStreamReader(const QByteArray& data);
~XmlStreamReader();
virtual ~XmlStreamReader();
void setData(const QByteArray& data);

View file

@ -0,0 +1,157 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-CLA-applies
*
* MuseScore
* Music Composition & Notation
*
* Copyright (C) 2021 MuseScore BVBA and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "xmlstreamwriter.h"
#include <QTextStream>
#include "containers.h"
using namespace mu;
XmlStreamWriter::XmlStreamWriter()
{
m_stream = new QTextStream();
m_stream->setCodec("UTF-8");
}
XmlStreamWriter::XmlStreamWriter(QIODevice* dev)
{
m_stream = new QTextStream(dev);
m_stream->setCodec("UTF-8");
}
XmlStreamWriter::~XmlStreamWriter()
{
delete m_stream;
}
void XmlStreamWriter::setDevice(QIODevice* dev)
{
m_stream->setDevice(dev);
}
void XmlStreamWriter::setString(QString* string, QIODevice::OpenMode openMode)
{
m_stream->setString(string, openMode);
}
void XmlStreamWriter::flush()
{
m_stream->flush();
}
void XmlStreamWriter::putLevel()
{
size_t level = m_stack.size();
for (size_t i = 0; i < level * 2; ++i) {
*m_stream << ' ';
}
}
void XmlStreamWriter::writeHeader()
{
*m_stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
}
void XmlStreamWriter::writeDoctype(const QString& type)
{
*m_stream << "<!DOCTYPE " << type << ">\n";
}
void XmlStreamWriter::writeStartElement(const QString& name)
{
putLevel();
*m_stream << '<' << name << '>' << Qt::endl;
m_stack.push_back(name.split(' ')[0]);
}
void XmlStreamWriter::writeStartElement(const QString& name, const QString& attributes)
{
putLevel();
*m_stream << '<' << name;
if (!attributes.isEmpty()) {
*m_stream << ' ' << attributes;
}
*m_stream << '>' << Qt::endl;
m_stack.push_back(name);
}
void XmlStreamWriter::writeEndElement()
{
putLevel();
*m_stream << "</" << mu::takeLast(m_stack) << '>' << Qt::endl;
}
void XmlStreamWriter::writeElement(const QString& name, const QString& val)
{
if (name == "measureNumberVPlacement") {
int k = -1;
}
QString ename(QString(name).split(' ')[0]);
putLevel();
*m_stream << "<" << name << ">";
*m_stream << val;
*m_stream << "</" << ename << ">\n";
}
void XmlStreamWriter::writeElement(const QString& name, int val)
{
if (name == "measureNumberVPlacement") {
int k = -1;
}
QString ename(QString(name).split(' ')[0]);
putLevel();
*m_stream << "<" << name << ">";
*m_stream << val;
*m_stream << "</" << ename << ">\n";
}
void XmlStreamWriter::writeElement(const QString& name, qint64 val)
{
QString ename(QString(name).split(' ')[0]);
putLevel();
*m_stream << "<" << name << ">";
*m_stream << val;
*m_stream << "</" << ename << ">\n";
}
void XmlStreamWriter::writeElement(const QString& name, double val)
{
QString ename(QString(name).split(' ')[0]);
putLevel();
*m_stream << "<" << name << ">";
*m_stream << val;
*m_stream << "</" << ename << ">\n";
}
void XmlStreamWriter::writeElement(const QString& nameWithAttributes)
{
putLevel();
*m_stream << '<' << nameWithAttributes << "/>\n";
}
void XmlStreamWriter::writeComment(const QString& text)
{
putLevel();
*m_stream << "<!-- " << text << " -->\n";
}

View file

@ -0,0 +1,70 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-CLA-applies
*
* MuseScore
* Music Composition & Notation
*
* Copyright (C) 2021 MuseScore BVBA and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef MU_GLOBAL_XMLSTREAMWRITER_H
#define MU_GLOBAL_XMLSTREAMWRITER_H
#include <list>
#include <QIODevice>
#include <QString>
class QTextStream;
namespace mu {
class XmlStreamWriter
{
public:
XmlStreamWriter();
explicit XmlStreamWriter(QIODevice* dev);
virtual ~XmlStreamWriter();
void setDevice(QIODevice* dev);
void setString(QString* string, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
void flush();
void writeHeader();
void writeDoctype(const QString& type);
void writeStartElement(const QString& name);
void writeStartElement(const QString& name, const QString& attributes);
void writeEndElement();
void writeElement(const QString& name, const QString& val);
void writeElement(const QString& name, int val);
void writeElement(const QString& name, qint64 val);
void writeElement(const QString& name, double val);
void writeElement(const QString& nameWithAttributes);
void writeComment(const QString& text);
private:
void putLevel();
std::list<QString> m_stack;
//! NOTE Temporary implementation
QTextStream* m_stream = nullptr;
};
}
#endif // MU_GLOBAL_XMLSTREAMWRITER_H

View file

@ -7260,11 +7260,8 @@ void ExportMusicXml::write(QIODevice* dev)
_jumpElements = findJumpElements(_score);
_xml.setDevice(dev);
_xml.setCodec("UTF-8");
_xml << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
_xml
<<
"<!DOCTYPE score-partwise PUBLIC \"-//Recordare//DTD MusicXML 4.0 Partwise//EN\" \"http://www.musicxml.org/dtds/partwise.dtd\">\n";
_xml.writeHeader();
_xml.writeDoctype("score-partwise PUBLIC \"-//Recordare//DTD MusicXML 4.0 Partwise//EN\" \"http://www.musicxml.org/dtds/partwise.dtd\"");
_xml.startObject("score-partwise version=\"4.0\"");
@ -7343,8 +7340,7 @@ static void writeMxlArchive(Score* score, MQZipWriter& zipwriter, const QString&
XmlWriter xml;
xml.setDevice(&cbuf);
xml.setCodec("UTF-8");
xml << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
xml.writeHeader();
xml.startObject("container");
xml.startObject("rootfiles");
xml.startObject(QString("rootfile full-path=\"%1\"").arg(XmlWriter::xmlString(filename)));