2012-05-26 14:26:10 +02:00
|
|
|
|
//=============================================================================
|
|
|
|
|
// MuseScore
|
|
|
|
|
// Music Composition & Notation
|
|
|
|
|
//
|
2012-11-19 09:29:46 +01:00
|
|
|
|
// Copyright (C) 2011-2012 Werner Schweer and others
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//
|
|
|
|
|
// 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 LICENSE.GPL
|
|
|
|
|
//=============================================================================
|
|
|
|
|
|
2012-07-16 15:49:24 +02:00
|
|
|
|
#include "config.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
|
#include "score.h"
|
|
|
|
|
#include "xml.h"
|
|
|
|
|
#include "element.h"
|
|
|
|
|
#include "measure.h"
|
|
|
|
|
#include "segment.h"
|
|
|
|
|
#include "slur.h"
|
|
|
|
|
#include "chordrest.h"
|
2013-01-04 17:48:15 +01:00
|
|
|
|
#include "chord.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
|
#include "tuplet.h"
|
|
|
|
|
#include "beam.h"
|
|
|
|
|
#include "revisions.h"
|
|
|
|
|
#include "page.h"
|
|
|
|
|
#include "part.h"
|
|
|
|
|
#include "staff.h"
|
2013-06-10 11:03:34 +02:00
|
|
|
|
#include "system.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
|
#include "keysig.h"
|
|
|
|
|
#include "clef.h"
|
|
|
|
|
#include "text.h"
|
|
|
|
|
#include "ottava.h"
|
|
|
|
|
#include "volta.h"
|
|
|
|
|
#include "excerpt.h"
|
|
|
|
|
#include "mscore.h"
|
|
|
|
|
#include "stafftype.h"
|
2015-04-08 09:10:46 +02:00
|
|
|
|
#include "sym.h"
|
2015-10-01 15:03:32 +02:00
|
|
|
|
|
2012-07-06 17:42:20 +02:00
|
|
|
|
#ifdef OMR
|
2012-05-26 14:26:10 +02:00
|
|
|
|
#include "omr/omr.h"
|
|
|
|
|
#include "omr/omrpage.h"
|
2012-07-06 17:42:20 +02:00
|
|
|
|
#endif
|
2015-10-01 15:03:32 +02:00
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
|
#include "sig.h"
|
|
|
|
|
#include "undo.h"
|
|
|
|
|
#include "imageStore.h"
|
|
|
|
|
#include "audio.h"
|
2012-10-20 20:32:40 +02:00
|
|
|
|
#include "barline.h"
|
2014-05-07 09:28:19 +02:00
|
|
|
|
#include "thirdparty/qzip/qzipreader_p.h"
|
|
|
|
|
#include "thirdparty/qzip/qzipwriter_p.h"
|
2013-05-17 18:02:34 +02:00
|
|
|
|
#ifdef Q_OS_WIN
|
2013-04-18 15:47:07 +02:00
|
|
|
|
#include <windows.h>
|
|
|
|
|
#endif
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
|
namespace Ms {
|
|
|
|
|
|
2013-09-19 15:08:54 +02:00
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// writeMeasure
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2017-03-09 23:55:10 +01:00
|
|
|
|
static void writeMeasure(XmlWriter& xml, MeasureBase* m, int staffIdx, bool writeSystemElements, bool forceTimeSig)
|
2013-09-19 15:08:54 +02:00
|
|
|
|
{
|
2013-10-28 15:52:32 +01:00
|
|
|
|
//
|
|
|
|
|
// special case multi measure rest
|
|
|
|
|
//
|
2016-03-02 13:20:19 +01:00
|
|
|
|
if (m->isMeasure() || staffIdx == 0)
|
2017-03-09 23:55:10 +01:00
|
|
|
|
m->write(xml, staffIdx, writeSystemElements, forceTimeSig);
|
2014-02-26 19:06:42 +01:00
|
|
|
|
|
2018-03-27 15:36:00 +02:00
|
|
|
|
if (m->score()->styleB(Sid::createMultiMeasureRests) && m->isMeasure() && toMeasure(m)->mmRest())
|
2017-03-09 23:55:10 +01:00
|
|
|
|
toMeasure(m)->mmRest()->write(xml, staffIdx, writeSystemElements, forceTimeSig);
|
2014-07-28 18:01:38 +02:00
|
|
|
|
|
2016-11-19 10:31:14 +01:00
|
|
|
|
xml.setCurTick(m->endTick());
|
2013-09-19 15:08:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//---------------------------------------------------------
|
2017-01-05 11:23:47 +01:00
|
|
|
|
// writeMovement
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2017-01-05 11:23:47 +01:00
|
|
|
|
void Score::writeMovement(XmlWriter& xml, bool selectionOnly)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
2014-07-28 18:01:38 +02:00
|
|
|
|
// if we have multi measure rests and some parts are hidden,
|
|
|
|
|
// then some layout information is missing:
|
|
|
|
|
// relayout with all parts set visible
|
|
|
|
|
|
2014-10-30 09:36:30 +01:00
|
|
|
|
QList<Part*> hiddenParts;
|
2014-07-28 18:01:38 +02:00
|
|
|
|
bool unhide = false;
|
2018-03-27 15:36:00 +02:00
|
|
|
|
if (styleB(Sid::createMultiMeasureRests)) {
|
2014-07-28 18:01:38 +02:00
|
|
|
|
for (Part* part : _parts) {
|
|
|
|
|
if (!part->show()) {
|
2014-10-30 09:36:30 +01:00
|
|
|
|
if (!unhide) {
|
|
|
|
|
startCmd();
|
|
|
|
|
unhide = true;
|
|
|
|
|
}
|
2018-03-27 15:36:00 +02:00
|
|
|
|
part->undoChangeProperty(Pid::VISIBLE, true);
|
2014-10-30 09:36:30 +01:00
|
|
|
|
hiddenParts.append(part);
|
2014-07-28 18:01:38 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (unhide) {
|
|
|
|
|
doLayout();
|
2014-10-30 09:36:30 +01:00
|
|
|
|
for (Part* p : hiddenParts)
|
|
|
|
|
p->setShow(false);
|
2014-07-28 18:01:38 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-26 12:20:00 +02:00
|
|
|
|
xml.stag(this);
|
2016-07-31 15:23:11 +02:00
|
|
|
|
if (excerpt()) {
|
|
|
|
|
Excerpt* e = excerpt();
|
|
|
|
|
QMultiMap<int, int> trackList = e->tracks();
|
|
|
|
|
QMapIterator<int, int> i(trackList);
|
|
|
|
|
if (!(trackList.size() == e->parts().size() * VOICES) && !trackList.isEmpty()) {
|
|
|
|
|
while (i.hasNext()) {
|
|
|
|
|
i.next();
|
2016-09-19 13:58:13 +02:00
|
|
|
|
xml.tagE(QString("Tracklist sTrack=\"%1\" dstTrack=\"%2\"").arg(i.key()).arg(i.value()));
|
2016-07-31 15:23:11 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-31 11:54:16 +02:00
|
|
|
|
if (lineMode())
|
2017-01-05 11:23:47 +01:00
|
|
|
|
xml.tag("layoutMode", "line");
|
2018-08-31 11:54:16 +02:00
|
|
|
|
if (systemMode())
|
|
|
|
|
xml.tag("layoutMode", "system");
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2012-07-06 17:42:20 +02:00
|
|
|
|
#ifdef OMR
|
2016-11-19 10:31:14 +01:00
|
|
|
|
if (masterScore()->omr() && xml.writeOmr())
|
2015-11-12 16:20:17 +01:00
|
|
|
|
masterScore()->omr()->write(xml);
|
2012-07-06 17:42:20 +02:00
|
|
|
|
#endif
|
2016-11-19 10:31:14 +01:00
|
|
|
|
if (isMaster() && masterScore()->showOmr() && xml.writeOmr())
|
2016-03-10 10:41:31 +01:00
|
|
|
|
xml.tag("showOmr", masterScore()->showOmr());
|
2016-11-19 10:31:14 +01:00
|
|
|
|
if (_audio && xml.writeOmr()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
|
xml.tag("playMode", int(_playMode));
|
|
|
|
|
_audio->write(xml);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 32; ++i) {
|
|
|
|
|
if (!_layerTags[i].isEmpty()) {
|
|
|
|
|
xml.tag(QString("LayerTag id=\"%1\" tag=\"%2\"").arg(i).arg(_layerTags[i]),
|
|
|
|
|
_layerTagComments[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int n = _layer.size();
|
2018-11-27 22:49:18 +01:00
|
|
|
|
for (int i = 1; i < n; ++i) { // don’t save default variant
|
2012-05-26 14:26:10 +02:00
|
|
|
|
const Layer& l = _layer[i];
|
|
|
|
|
xml.tagE(QString("Layer name=\"%1\" mask=\"%2\"").arg(l.name).arg(l.tags));
|
|
|
|
|
}
|
|
|
|
|
xml.tag("currentLayer", _currentLayer);
|
|
|
|
|
|
2017-01-05 11:23:47 +01:00
|
|
|
|
if (isTopScore() && !MScore::testMode)
|
2013-04-02 20:46:07 +02:00
|
|
|
|
_synthesizerState.write(xml);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
|
|
if (pageNumberOffset())
|
|
|
|
|
xml.tag("page-offset", pageNumberOffset());
|
|
|
|
|
xml.tag("Division", MScore::division);
|
2016-11-19 10:31:14 +01:00
|
|
|
|
xml.setCurTrack(-1);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2017-01-05 11:23:47 +01:00
|
|
|
|
if (isTopScore()) // only top score
|
|
|
|
|
style().save(xml, true); // save only differences to buildin style
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2016-03-11 12:18:46 +01:00
|
|
|
|
xml.tag("showInvisible", _showInvisible);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
xml.tag("showUnprintable", _showUnprintable);
|
2016-03-11 12:18:46 +01:00
|
|
|
|
xml.tag("showFrames", _showFrames);
|
|
|
|
|
xml.tag("showMargins", _showPageborders);
|
2019-05-02 18:46:44 +02:00
|
|
|
|
xml.tag("markIrregularMeasures", _markIrregularMeasures, true);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
|
|
QMapIterator<QString, QString> i(_metaTags);
|
|
|
|
|
while (i.hasNext()) {
|
|
|
|
|
i.next();
|
2018-09-25 11:10:55 +02:00
|
|
|
|
// do not output "platform" and "creationDate" in test and save template mode
|
|
|
|
|
if ((!MScore::testMode && !MScore::saveTemplateMode) || (i.key() != "platform" && i.key() != "creationDate"))
|
2014-10-11 21:00:17 +02:00
|
|
|
|
xml.tag(QString("metaTag name=\"%1\"").arg(i.key().toHtmlEscaped()), i.value());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-19 10:31:14 +01:00
|
|
|
|
xml.setCurTrack(0);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
int staffStart;
|
|
|
|
|
int staffEnd;
|
|
|
|
|
MeasureBase* measureStart;
|
|
|
|
|
MeasureBase* measureEnd;
|
|
|
|
|
|
|
|
|
|
if (selectionOnly) {
|
|
|
|
|
staffStart = _selection.staffStart();
|
|
|
|
|
staffEnd = _selection.staffEnd();
|
2015-06-30 17:19:58 +02:00
|
|
|
|
// make sure we select full parts
|
|
|
|
|
Staff* sStaff = staff(staffStart);
|
|
|
|
|
Part* sPart = sStaff->part();
|
|
|
|
|
Staff* eStaff = staff(staffEnd - 1);
|
|
|
|
|
Part* ePart = eStaff->part();
|
|
|
|
|
staffStart = staffIdx(sPart);
|
|
|
|
|
staffEnd = staffIdx(ePart) + ePart->nstaves();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
measureStart = _selection.startSegment()->measure();
|
2018-11-16 18:07:54 +01:00
|
|
|
|
if (measureStart->isMeasure() && toMeasure(measureStart)->isMMRest())
|
|
|
|
|
measureStart = toMeasure(measureStart)->mmRestFirst();
|
2013-08-01 15:14:24 +02:00
|
|
|
|
if (_selection.endSegment())
|
|
|
|
|
measureEnd = _selection.endSegment()->measure()->next();
|
|
|
|
|
else
|
|
|
|
|
measureEnd = 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
staffStart = 0;
|
|
|
|
|
staffEnd = nstaves();
|
|
|
|
|
measureStart = first();
|
|
|
|
|
measureEnd = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-10 17:52:00 +02:00
|
|
|
|
// Let's decide: write midi mapping to a file or not
|
2016-03-11 12:18:46 +01:00
|
|
|
|
masterScore()->checkMidiMapping();
|
|
|
|
|
for (const Part* part : _parts) {
|
2015-03-03 18:14:11 +01:00
|
|
|
|
if (!selectionOnly || ((staffIdx(part) >= staffStart) && (staffEnd >= staffIdx(part) + part->nstaves())))
|
|
|
|
|
part->write(xml);
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-19 10:31:14 +01:00
|
|
|
|
xml.setCurTrack(0);
|
|
|
|
|
xml.setTrackDiff(-staffStart * VOICES);
|
2013-05-06 21:35:08 +02:00
|
|
|
|
if (measureStart) {
|
|
|
|
|
for (int staffIdx = staffStart; staffIdx < staffEnd; ++staffIdx) {
|
2018-09-26 12:20:00 +02:00
|
|
|
|
xml.stag(staff(staffIdx), QString("id=\"%1\"").arg(staffIdx + 1 - staffStart));
|
2016-11-19 10:31:14 +01:00
|
|
|
|
xml.setCurTick(measureStart->tick());
|
|
|
|
|
xml.setTickDiff(xml.curTick());
|
|
|
|
|
xml.setCurTrack(staffIdx * VOICES);
|
2016-06-01 23:24:05 +02:00
|
|
|
|
bool writeSystemElements = (staffIdx == staffStart);
|
2017-03-09 23:55:10 +01:00
|
|
|
|
bool firstMeasureWritten = false;
|
|
|
|
|
bool forceTimeSig = false;
|
|
|
|
|
for (MeasureBase* m = measureStart; m != measureEnd; m = m->next()) {
|
|
|
|
|
// force timesig if first measure and selectionOnly
|
|
|
|
|
if (selectionOnly && m->isMeasure()) {
|
|
|
|
|
if (!firstMeasureWritten) {
|
|
|
|
|
forceTimeSig = true;
|
|
|
|
|
firstMeasureWritten = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
forceTimeSig = false;
|
|
|
|
|
}
|
|
|
|
|
writeMeasure(xml, m, staffIdx, writeSystemElements, forceTimeSig);
|
|
|
|
|
}
|
2013-05-06 21:35:08 +02:00
|
|
|
|
xml.etag();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-19 10:31:14 +01:00
|
|
|
|
xml.setCurTrack(-1);
|
2016-03-11 12:18:46 +01:00
|
|
|
|
if (isMaster()) {
|
|
|
|
|
if (!selectionOnly) {
|
|
|
|
|
for (const Excerpt* excerpt : excerpts()) {
|
|
|
|
|
if (excerpt->partScore() != this)
|
|
|
|
|
excerpt->partScore()->write(xml, false); // recursion
|
|
|
|
|
}
|
2012-12-18 09:09:11 +01:00
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2016-03-11 12:18:46 +01:00
|
|
|
|
else
|
2016-10-10 18:37:28 +02:00
|
|
|
|
xml.tag("name", excerpt()->title());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
xml.etag();
|
2014-07-28 18:01:38 +02:00
|
|
|
|
|
2019-05-04 15:16:46 +02:00
|
|
|
|
if (unhide)
|
|
|
|
|
endCmd(true);
|
2017-01-05 11:23:47 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// write
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void Score::write(XmlWriter& xml, bool selectionOnly)
|
|
|
|
|
{
|
|
|
|
|
if (isMaster()) {
|
|
|
|
|
MasterScore* score = static_cast<MasterScore*>(this);
|
|
|
|
|
while (score->prev())
|
|
|
|
|
score = score->prev();
|
|
|
|
|
while (score) {
|
|
|
|
|
score->writeMovement(xml, selectionOnly);
|
|
|
|
|
score = score->next();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
writeMovement(xml, selectionOnly);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2016-07-31 15:23:11 +02:00
|
|
|
|
// Staff
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
|
void Score::readStaff(XmlReader& e)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
2014-04-23 20:59:32 +02:00
|
|
|
|
int staff = e.intAttribute("id", 1) - 1;
|
2018-05-23 00:32:33 +02:00
|
|
|
|
int measureIdx = 0;
|
|
|
|
|
e.setCurrentMeasureIndex(0);
|
2019-01-30 15:13:54 +01:00
|
|
|
|
e.setTick(Fraction(0,1));
|
2013-01-21 20:21:41 +01:00
|
|
|
|
e.setTrack(staff * VOICES);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2014-04-23 20:59:32 +02:00
|
|
|
|
if (staff == 0) {
|
|
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
|
const QStringRef& tag(e.name());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2014-04-23 20:59:32 +02:00
|
|
|
|
if (tag == "Measure") {
|
|
|
|
|
Measure* measure = 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
measure = new Measure(this);
|
2013-01-21 20:21:41 +01:00
|
|
|
|
measure->setTick(e.tick());
|
2018-05-23 00:32:33 +02:00
|
|
|
|
e.setCurrentMeasureIndex(measureIdx++);
|
2016-09-13 09:39:50 +02:00
|
|
|
|
//
|
|
|
|
|
// inherit timesig from previous measure
|
|
|
|
|
//
|
|
|
|
|
Measure* m = e.lastMeasure(); // measure->prevMeasure();
|
|
|
|
|
Fraction f(m ? m->timesig() : Fraction(4,4));
|
2019-01-30 15:13:54 +01:00
|
|
|
|
measure->setTicks(f);
|
2016-09-13 09:39:50 +02:00
|
|
|
|
measure->setTimesig(f);
|
|
|
|
|
|
2014-04-23 20:59:32 +02:00
|
|
|
|
measure->read(e, staff);
|
2016-09-09 09:33:11 +02:00
|
|
|
|
measure->checkMeasure(staff);
|
2014-04-23 20:59:32 +02:00
|
|
|
|
if (!measure->isMMRest()) {
|
2014-07-03 15:02:36 +02:00
|
|
|
|
measures()->add(measure);
|
2014-04-23 20:59:32 +02:00
|
|
|
|
e.setLastMeasure(measure);
|
2019-01-30 15:13:54 +01:00
|
|
|
|
e.setTick(measure->tick() + measure->ticks());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2014-10-10 14:24:37 +02:00
|
|
|
|
else {
|
|
|
|
|
// this is a multi measure rest
|
|
|
|
|
// always preceded by the first measure it replaces
|
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs.
Most warnings are in the following categories:
- Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes)
- Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour.
- Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out.
- (Potentially) uninitialized local variable. Just initialized the vars.
- foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"."
Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types.
- all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h)
- awl/aslider.h: unreachable code.
- awl/knob.cpp: name hiding
- awl/mslider.cpp: name hiding
- awl/slider.cpp: name hiding
- bww2mxml/parser.cpp: name hiding
- effects/compressor/compressor.cpp: narrowing conversion
- effects/zita1/zitagui.cpp: name hiding
- fluid/fluid.cpp: foreach replacement. Name hiding.
- fluid/mod.cpp: name hiding.
- fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars.
- fluid/voice.cpp: Name hiding.
- libmscore/accidental.cpp: Name hiding.
- libmscore/ambitus.cpp: Initialize vars.
- libmscore/barline.cpp: Name hiding. Unreachable code.
- libmscore/beam.cpp: Name hiding.
- libmscore/chordrest.cpp: Unreachable code.
- libmscore/scorefile.cpp: Name hiding.
- manual/genManual.cpp: Name hiding. foreach replacement.
- midi/midifile.cpp: Name hiding. Unreachable code.
- omr/importpdf.cpp: Name hiding. foreach replacement.
- omr/omr.cpp: Name hiding. foreach replacement.
- omr/omrpage.cpp: Name hiding. foreach replacement.
- omr/omrview.cpp: Name hiding. foreach replacement.
- synthesizer/event.cpp: Unreachable code.
- zerberus\channel.cpp: Narrowing conversion.
- zerberus\instrument.cpp: Name hiding.
- zerberus\sfz.cpp: Name hiding.
- zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union"
- zerberus\zerberus.cpp: Name hiding. Unreferenced parameter.
- zerberus\zerberusgui.cpp: Name hiding.
2018-05-03 03:04:08 +02:00
|
|
|
|
Measure* m1 = e.lastMeasure();
|
2014-10-10 14:24:37 +02:00
|
|
|
|
|
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs.
Most warnings are in the following categories:
- Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes)
- Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour.
- Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out.
- (Potentially) uninitialized local variable. Just initialized the vars.
- foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"."
Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types.
- all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h)
- awl/aslider.h: unreachable code.
- awl/knob.cpp: name hiding
- awl/mslider.cpp: name hiding
- awl/slider.cpp: name hiding
- bww2mxml/parser.cpp: name hiding
- effects/compressor/compressor.cpp: narrowing conversion
- effects/zita1/zitagui.cpp: name hiding
- fluid/fluid.cpp: foreach replacement. Name hiding.
- fluid/mod.cpp: name hiding.
- fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars.
- fluid/voice.cpp: Name hiding.
- libmscore/accidental.cpp: Name hiding.
- libmscore/ambitus.cpp: Initialize vars.
- libmscore/barline.cpp: Name hiding. Unreachable code.
- libmscore/beam.cpp: Name hiding.
- libmscore/chordrest.cpp: Unreachable code.
- libmscore/scorefile.cpp: Name hiding.
- manual/genManual.cpp: Name hiding. foreach replacement.
- midi/midifile.cpp: Name hiding. Unreachable code.
- omr/importpdf.cpp: Name hiding. foreach replacement.
- omr/omr.cpp: Name hiding. foreach replacement.
- omr/omrpage.cpp: Name hiding. foreach replacement.
- omr/omrview.cpp: Name hiding. foreach replacement.
- synthesizer/event.cpp: Unreachable code.
- zerberus\channel.cpp: Narrowing conversion.
- zerberus\instrument.cpp: Name hiding.
- zerberus\sfz.cpp: Name hiding.
- zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union"
- zerberus\zerberus.cpp: Name hiding. Unreferenced parameter.
- zerberus\zerberusgui.cpp: Name hiding.
2018-05-03 03:04:08 +02:00
|
|
|
|
if (m1) {
|
|
|
|
|
m1->setMMRest(measure);
|
|
|
|
|
measure->setTick(m1->tick());
|
2014-10-10 14:24:37 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-04-23 20:59:32 +02:00
|
|
|
|
}
|
|
|
|
|
else if (tag == "HBox" || tag == "VBox" || tag == "TBox" || tag == "FBox") {
|
2017-12-20 16:49:30 +01:00
|
|
|
|
MeasureBase* mb = toMeasureBase(Element::name2Element(tag, this));
|
2014-04-23 20:59:32 +02:00
|
|
|
|
mb->read(e);
|
|
|
|
|
mb->setTick(e.tick());
|
2014-07-03 15:02:36 +02:00
|
|
|
|
measures()->add(mb);
|
2014-04-23 20:59:32 +02:00
|
|
|
|
}
|
|
|
|
|
else if (tag == "tick")
|
2019-01-30 15:13:54 +01:00
|
|
|
|
e.setTick(Fraction::fromTicks(fileDivision(e.readInt())));
|
2014-04-23 20:59:32 +02:00
|
|
|
|
else
|
|
|
|
|
e.unknown();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Measure* measure = firstMeasure();
|
|
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
|
const QStringRef& tag(e.name());
|
|
|
|
|
|
|
|
|
|
if (tag == "Measure") {
|
2012-05-26 14:26:10 +02:00
|
|
|
|
if (measure == 0) {
|
2014-03-25 13:33:47 +01:00
|
|
|
|
qDebug("Score::readStaff(): missing measure!");
|
2012-05-26 14:26:10 +02:00
|
|
|
|
measure = new Measure(this);
|
2013-01-21 20:21:41 +01:00
|
|
|
|
measure->setTick(e.tick());
|
2014-07-03 15:02:36 +02:00
|
|
|
|
measures()->add(measure);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2019-01-30 15:13:54 +01:00
|
|
|
|
e.setTick(measure->tick());
|
2018-05-23 00:32:33 +02:00
|
|
|
|
e.setCurrentMeasureIndex(measureIdx++);
|
2014-04-23 20:59:32 +02:00
|
|
|
|
measure->read(e, staff);
|
2016-09-09 09:33:11 +02:00
|
|
|
|
measure->checkMeasure(staff);
|
2014-04-23 20:59:32 +02:00
|
|
|
|
if (measure->isMMRest())
|
|
|
|
|
measure = e.lastMeasure()->nextMeasure();
|
|
|
|
|
else {
|
|
|
|
|
e.setLastMeasure(measure);
|
|
|
|
|
if (measure->mmRest())
|
|
|
|
|
measure = measure->mmRest();
|
|
|
|
|
else
|
|
|
|
|
measure = measure->nextMeasure();
|
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2014-04-23 20:59:32 +02:00
|
|
|
|
else if (tag == "tick")
|
2019-01-30 15:13:54 +01:00
|
|
|
|
e.setTick(Fraction::fromTicks(fileDivision(e.readInt())));
|
2014-04-23 20:59:32 +02:00
|
|
|
|
else
|
|
|
|
|
e.unknown();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// saveFile
|
|
|
|
|
/// If file has generated name, create a modal file save dialog
|
|
|
|
|
/// and ask filename.
|
|
|
|
|
/// Rename old file to backup file (.xxxx.msc?,).
|
|
|
|
|
/// Default is to save score in .mscz format,
|
|
|
|
|
/// Return true if OK and false on error.
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
|
bool MasterScore::saveFile()
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
2018-08-03 01:15:56 +02:00
|
|
|
|
if (readOnly())
|
|
|
|
|
return false;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
QString suffix = info.suffix();
|
|
|
|
|
if (info.exists() && !info.isWritable()) {
|
2017-08-14 11:48:58 +02:00
|
|
|
|
MScore::lastError = tr("The following file is locked: \n%1 \n\nTry saving to a different location.").arg(info.filePath());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
//
|
|
|
|
|
// step 1
|
|
|
|
|
// save into temporary file to prevent partially overwriting
|
|
|
|
|
// the original file in case of "disc full"
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
QString tempName = info.filePath() + QString(".temp");
|
|
|
|
|
QFile temp(tempName);
|
|
|
|
|
if (!temp.open(QIODevice::WriteOnly)) {
|
2017-08-14 11:48:58 +02:00
|
|
|
|
MScore::lastError = tr("Open Temp File\n%1\nfailed: %2").arg(tempName, strerror(errno));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-09-16 18:31:33 +02:00
|
|
|
|
bool rv = suffix == "mscx" ? Score::saveFile(&temp, false) : Score::saveCompressedFile(&temp, info, false);
|
|
|
|
|
if (!rv) {
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return false;
|
2016-09-16 18:31:33 +02:00
|
|
|
|
}
|
2016-09-14 12:08:14 +02:00
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
|
if (temp.error() != QFile::NoError) {
|
2017-08-14 11:48:58 +02:00
|
|
|
|
MScore::lastError = tr("Save File failed: %1").arg(temp.errorString());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
temp.close();
|
|
|
|
|
|
2015-11-24 09:42:37 +01:00
|
|
|
|
QString name(info.filePath());
|
2017-10-10 21:02:30 +02:00
|
|
|
|
QString basename(info.fileName());
|
2015-12-02 17:23:58 +01:00
|
|
|
|
QDir dir(info.path());
|
2015-11-24 09:42:37 +01:00
|
|
|
|
if (!saved()) {
|
|
|
|
|
// if file was already saved in this session
|
|
|
|
|
// save but don't overwrite backup again
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// step 2
|
|
|
|
|
// remove old backup file if exists
|
|
|
|
|
//
|
|
|
|
|
QString backupName = QString(".") + info.fileName() + QString(",");
|
|
|
|
|
if (dir.exists(backupName)) {
|
|
|
|
|
if (!dir.remove(backupName)) {
|
|
|
|
|
// if (!MScore::noGui)
|
2017-03-28 18:54:29 +02:00
|
|
|
|
// QMessageBox::critical(0, QObject::tr("Save File"),
|
2017-08-14 11:48:58 +02:00
|
|
|
|
// tr("Removing old backup file %1 failed").arg(backupName));
|
2015-11-24 09:42:37 +01:00
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
2015-11-24 09:42:37 +01:00
|
|
|
|
//
|
|
|
|
|
// step 3
|
|
|
|
|
// rename old file into backup
|
|
|
|
|
//
|
2017-10-10 21:02:30 +02:00
|
|
|
|
if (dir.exists(basename)) {
|
|
|
|
|
if (!dir.rename(basename, backupName)) {
|
2015-11-24 09:42:37 +01:00
|
|
|
|
// if (!MScore::noGui)
|
2017-03-28 18:54:29 +02:00
|
|
|
|
// QMessageBox::critical(0, tr("Save File"),
|
2017-08-14 11:48:58 +02:00
|
|
|
|
// tr("Renaming old file <%1> to backup <%2> failed").arg(name, backupname);
|
2015-11-24 09:42:37 +01:00
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2018-08-03 01:18:26 +02:00
|
|
|
|
|
2015-11-24 10:47:27 +01:00
|
|
|
|
QFileInfo fileBackup(dir, backupName);
|
2018-08-03 01:18:26 +02:00
|
|
|
|
_sessionStartBackupInfo = fileBackup;
|
|
|
|
|
|
|
|
|
|
#ifdef Q_OS_WIN
|
2015-11-24 10:47:27 +01:00
|
|
|
|
QString backupNativePath = QDir::toNativeSeparators(fileBackup.absoluteFilePath());
|
Solved all compilation errors on MSVC
This commit contains changes required for MuseScore to compile under MSVC with no errors.
There are several general categories of problems that resulted in errors with the compilation. Main issues:
- Variable Length Arrays (VLA). This is a non-standard extension to C++, supported by clang toolchains, but not by MSVC. The initial workaround is to use std::vector<> instead of VLAs, eventually (if needed) with the original variable pointing to the beginning of the allocated array. More efficient alternatives are possible if profiling shows any code using VLAs to be timing-critical.
- Floating-point constants not suffixed with "f" are doubles by default; in some instances, this leads to narrowing conversion errors (in other instances, just warnings).
- MSVC does not support "or"/"and"/"not" in lieu of "||"/"&&"/"!". Changed unconditionally to use standard C++ symbols.
- MSVC does not support the "__builtin_unreachable()" compiler hint. A similar, albeit not exactly equal, alternative is "__assume(0)", which is MSVC-specific.
- MSVC does not support ranges in case statements. Replaced with list of cases instead of range (non-conditionally)
Detailed changes, with per-file comments:
- all.h: opt-in to deprecated features, include <io.h> and <process.h> instead of POSIX <unistd.h>, undefine "STRING_NONE" and "small", which Microsoft defines as macros, which result in compilation errors.
- effects/compressor/zita.cpp: eliminated narrowing conversion error by appending "f" to float constants.
- fluid/voice.cpp: appended "f" to float constants to eliminate narrowing conversion errors/warnings
- libmscore/beam.cpp: conditionally replaced VLA
- libmscore/edit.cpp: conditionally replaced VLA
- libmscore/element.cpp: appended "f" to float constant
- libmscore/fret.cpp: changed or -> ||
- libmscore/layout.cpp: conditionally replaced VLA
- libmscore/mscore.cpp: conditionally replaced "__builtin_unreachable()" with "__assume(0)" for MSVC
- libmscore/scorefile.coo: use correct char representation conversion for MSVC
- libmscore/stringdata.cpp: conditionally replaced VLA
- libmscore/system.cpp: conditionally replaced VLA
- libmscroe/text.cpp: replaced range in case statement.
- manual/genManual.cpp: use getopt() replacement.
- midi/midifile.cpp: conditionally replaced VLA. This does not use the default replacement.
- mscore/bb.cpp: replaced range in case statement.
- mscore/capella.cpp: conditionally replaced VLA. Changed and -> &&
- mscore/driver:cpp: preclude errors due to macro redefinitions.
- mscore/editstyle.cpp: conditionally replaced "__builtin_unreachable()" with "__assume(0)" for MSVC
- mscore/importgtp-gp6.cpp: conditionally replaced VLA.
- mscore/instrwidget.cpp: conditionally replaced VLA.
- mscore/jackaudio.cpp: conditionally replaced VLA. Preclude errors due to macro redefinitions.
- mscore/jackweakapi.cpp: Preclude errors due to macro redefinitions. Replacement for __atribute__((constructor)) through static object construction for MSVC. Force use of LoadLibraryA instead of LoadLibrary.
- mscore/mididriver.h: Changed not -> !
- mscore/musescore.cpp: Changed not -> !. Conditionally replaced VLA.
- mscore/resourceManager.cpp: conditionally replaced VLA.
- mscore/timeline.cpp: conditionally replaced VLA.
- omr/omrpage.cpp: conditionally replaced VLA.
- synthesizer/msynthesizer.cpp: replaced UNIX sleep(1) method with MSVC Sleep(1000) (equivalent, but in ms instead of seconds)
- synthesizer/msynthsizer.h: appended "f" to float constant
- thirdparty/poppler/config.h: set defines for MSVC to preclude the use of inexistent libraries.
- thirdparty/poppler/poppler/poppler-config.h: set defines for MSVC to preclude the use of inexistent libraries. Eliminated #defines for fmin and fmax which where causing problems.
- thirdparty/poppler/poppler/PSOutputDev.cc: added #include <algorithm> for std::min() and std::max(). Note this is required per-C++ standard.
- thirdparty/portmidi/pm_win/pmwinmm.c: undefined UNICODE to use char-based library functions.
- thirdparty/qzip/qzip.cpp: changed or -> ||
- thirdparty/rtf2html/rtf_keyword.h: file format changed from Apple to UNIX, as MSVC does not supported the former.
(NOT error related, just improvement on previous commit; manual/getopt/README.md: added link to source article)
2018-05-01 19:14:44 +02:00
|
|
|
|
#if (defined (_MSCVER) || defined (_MSC_VER))
|
|
|
|
|
#if (defined (UNICODE))
|
|
|
|
|
SetFileAttributes((LPCTSTR)backupNativePath.unicode(), FILE_ATTRIBUTE_HIDDEN);
|
|
|
|
|
#else
|
|
|
|
|
// Use byte-based Windows function
|
2015-11-24 10:47:27 +01:00
|
|
|
|
SetFileAttributes((LPCTSTR)backupNativePath.toLocal8Bit(), FILE_ATTRIBUTE_HIDDEN);
|
Solved all compilation errors on MSVC
This commit contains changes required for MuseScore to compile under MSVC with no errors.
There are several general categories of problems that resulted in errors with the compilation. Main issues:
- Variable Length Arrays (VLA). This is a non-standard extension to C++, supported by clang toolchains, but not by MSVC. The initial workaround is to use std::vector<> instead of VLAs, eventually (if needed) with the original variable pointing to the beginning of the allocated array. More efficient alternatives are possible if profiling shows any code using VLAs to be timing-critical.
- Floating-point constants not suffixed with "f" are doubles by default; in some instances, this leads to narrowing conversion errors (in other instances, just warnings).
- MSVC does not support "or"/"and"/"not" in lieu of "||"/"&&"/"!". Changed unconditionally to use standard C++ symbols.
- MSVC does not support the "__builtin_unreachable()" compiler hint. A similar, albeit not exactly equal, alternative is "__assume(0)", which is MSVC-specific.
- MSVC does not support ranges in case statements. Replaced with list of cases instead of range (non-conditionally)
Detailed changes, with per-file comments:
- all.h: opt-in to deprecated features, include <io.h> and <process.h> instead of POSIX <unistd.h>, undefine "STRING_NONE" and "small", which Microsoft defines as macros, which result in compilation errors.
- effects/compressor/zita.cpp: eliminated narrowing conversion error by appending "f" to float constants.
- fluid/voice.cpp: appended "f" to float constants to eliminate narrowing conversion errors/warnings
- libmscore/beam.cpp: conditionally replaced VLA
- libmscore/edit.cpp: conditionally replaced VLA
- libmscore/element.cpp: appended "f" to float constant
- libmscore/fret.cpp: changed or -> ||
- libmscore/layout.cpp: conditionally replaced VLA
- libmscore/mscore.cpp: conditionally replaced "__builtin_unreachable()" with "__assume(0)" for MSVC
- libmscore/scorefile.coo: use correct char representation conversion for MSVC
- libmscore/stringdata.cpp: conditionally replaced VLA
- libmscore/system.cpp: conditionally replaced VLA
- libmscroe/text.cpp: replaced range in case statement.
- manual/genManual.cpp: use getopt() replacement.
- midi/midifile.cpp: conditionally replaced VLA. This does not use the default replacement.
- mscore/bb.cpp: replaced range in case statement.
- mscore/capella.cpp: conditionally replaced VLA. Changed and -> &&
- mscore/driver:cpp: preclude errors due to macro redefinitions.
- mscore/editstyle.cpp: conditionally replaced "__builtin_unreachable()" with "__assume(0)" for MSVC
- mscore/importgtp-gp6.cpp: conditionally replaced VLA.
- mscore/instrwidget.cpp: conditionally replaced VLA.
- mscore/jackaudio.cpp: conditionally replaced VLA. Preclude errors due to macro redefinitions.
- mscore/jackweakapi.cpp: Preclude errors due to macro redefinitions. Replacement for __atribute__((constructor)) through static object construction for MSVC. Force use of LoadLibraryA instead of LoadLibrary.
- mscore/mididriver.h: Changed not -> !
- mscore/musescore.cpp: Changed not -> !. Conditionally replaced VLA.
- mscore/resourceManager.cpp: conditionally replaced VLA.
- mscore/timeline.cpp: conditionally replaced VLA.
- omr/omrpage.cpp: conditionally replaced VLA.
- synthesizer/msynthesizer.cpp: replaced UNIX sleep(1) method with MSVC Sleep(1000) (equivalent, but in ms instead of seconds)
- synthesizer/msynthsizer.h: appended "f" to float constant
- thirdparty/poppler/config.h: set defines for MSVC to preclude the use of inexistent libraries.
- thirdparty/poppler/poppler/poppler-config.h: set defines for MSVC to preclude the use of inexistent libraries. Eliminated #defines for fmin and fmax which where causing problems.
- thirdparty/poppler/poppler/PSOutputDev.cc: added #include <algorithm> for std::min() and std::max(). Note this is required per-C++ standard.
- thirdparty/portmidi/pm_win/pmwinmm.c: undefined UNICODE to use char-based library functions.
- thirdparty/qzip/qzip.cpp: changed or -> ||
- thirdparty/rtf2html/rtf_keyword.h: file format changed from Apple to UNIX, as MSVC does not supported the former.
(NOT error related, just improvement on previous commit; manual/getopt/README.md: added link to source article)
2018-05-01 19:14:44 +02:00
|
|
|
|
#endif
|
|
|
|
|
#else
|
|
|
|
|
SetFileAttributes((LPCTSTR)backupNativePath.toLocal8Bit(), FILE_ATTRIBUTE_HIDDEN);
|
|
|
|
|
#endif
|
2013-04-18 15:47:07 +02:00
|
|
|
|
#endif
|
2015-11-24 10:47:27 +01:00
|
|
|
|
}
|
2015-12-02 17:23:58 +01:00
|
|
|
|
else {
|
|
|
|
|
// file has previously been saved - remove the old file
|
2017-10-10 21:02:30 +02:00
|
|
|
|
if (dir.exists(basename)) {
|
|
|
|
|
if (!dir.remove(basename)) {
|
2015-12-02 17:23:58 +01:00
|
|
|
|
// if (!MScore::noGui)
|
2017-03-28 18:54:29 +02:00
|
|
|
|
// QMessageBox::critical(0, tr("Save File"),
|
2017-08-14 11:48:58 +02:00
|
|
|
|
// tr("Removing old file %1 failed").arg(name));
|
2015-12-02 17:23:58 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//
|
|
|
|
|
// step 4
|
|
|
|
|
// rename temp name into file name
|
|
|
|
|
//
|
|
|
|
|
if (!QFile::rename(tempName, name)) {
|
2017-08-14 11:48:58 +02:00
|
|
|
|
MScore::lastError = tr("Renaming temp. file <%1> to <%2> failed:\n%3").arg(tempName, name, strerror(errno));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// make file readable by all
|
|
|
|
|
QFile::setPermissions(name, QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser
|
|
|
|
|
| QFile::ReadGroup | QFile::ReadOther);
|
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
|
undoStack()->setClean();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
setSaved(true);
|
2014-09-30 13:24:27 +02:00
|
|
|
|
info.refresh();
|
|
|
|
|
update();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// saveCompressedFile
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2016-09-14 12:08:14 +02:00
|
|
|
|
bool Score::saveCompressedFile(QFileInfo& info, bool onlySelection)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
2018-08-03 01:15:56 +02:00
|
|
|
|
if (readOnly() && info == *masterScore()->fileInfo())
|
|
|
|
|
return false;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
QFile fp(info.filePath());
|
|
|
|
|
if (!fp.open(QIODevice::WriteOnly)) {
|
2017-08-14 11:48:58 +02:00
|
|
|
|
MScore::lastError = tr("Open File\n%1\nfailed: %2").arg(info.filePath(), strerror(errno));
|
2016-09-14 12:08:14 +02:00
|
|
|
|
return false;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2016-09-14 12:08:14 +02:00
|
|
|
|
return saveCompressedFile(&fp, info, onlySelection);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-11-14 13:17:56 +01:00
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// createThumbnail
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
QImage Score::createThumbnail()
|
|
|
|
|
{
|
2016-05-18 15:43:47 +02:00
|
|
|
|
LayoutMode mode = layoutMode();
|
|
|
|
|
setLayoutMode(LayoutMode::PAGE);
|
|
|
|
|
doLayout();
|
|
|
|
|
|
2014-11-14 13:17:56 +01:00
|
|
|
|
Page* page = pages().at(0);
|
|
|
|
|
QRectF fr = page->abbox();
|
|
|
|
|
qreal mag = 256.0 / qMax(fr.width(), fr.height());
|
|
|
|
|
int w = int(fr.width() * mag);
|
|
|
|
|
int h = int(fr.height() * mag);
|
|
|
|
|
|
|
|
|
|
QImage pm(w, h, QImage::Format_ARGB32_Premultiplied);
|
2016-09-26 12:02:05 +02:00
|
|
|
|
|
|
|
|
|
int dpm = lrint(DPMM * 1000.0);
|
|
|
|
|
pm.setDotsPerMeterX(dpm);
|
|
|
|
|
pm.setDotsPerMeterY(dpm);
|
2014-11-14 13:17:56 +01:00
|
|
|
|
pm.fill(0xffffffff);
|
2016-09-26 12:02:05 +02:00
|
|
|
|
|
|
|
|
|
double pr = MScore::pixelRatio;
|
|
|
|
|
MScore::pixelRatio = 1.0;
|
|
|
|
|
|
2014-11-14 13:17:56 +01:00
|
|
|
|
QPainter p(&pm);
|
|
|
|
|
p.setRenderHint(QPainter::Antialiasing, true);
|
|
|
|
|
p.setRenderHint(QPainter::TextAntialiasing, true);
|
|
|
|
|
p.scale(mag, mag);
|
|
|
|
|
print(&p, 0);
|
|
|
|
|
p.end();
|
2016-09-26 12:02:05 +02:00
|
|
|
|
|
|
|
|
|
MScore::pixelRatio = pr;
|
|
|
|
|
|
2016-05-18 15:43:47 +02:00
|
|
|
|
if (layoutMode() != mode) {
|
|
|
|
|
setLayoutMode(mode);
|
|
|
|
|
doLayout();
|
|
|
|
|
}
|
2014-11-14 13:17:56 +01:00
|
|
|
|
return pm;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// saveCompressedFile
|
|
|
|
|
// file is already opened
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2018-11-29 16:03:07 +01:00
|
|
|
|
bool Score::saveCompressedFile(QFileDevice* f, QFileInfo& info, bool onlySelection, bool doCreateThumbnail)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
2013-07-26 15:39:46 +02:00
|
|
|
|
MQZipWriter uz(f);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
|
|
QString fn = info.completeBaseName() + ".mscx";
|
|
|
|
|
QBuffer cbuf;
|
|
|
|
|
cbuf.open(QIODevice::ReadWrite);
|
2016-11-19 11:51:21 +01:00
|
|
|
|
XmlWriter xml(this, &cbuf);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
xml << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
|
|
|
|
xml.stag("container");
|
|
|
|
|
xml.stag("rootfiles");
|
2016-11-19 11:51:21 +01:00
|
|
|
|
xml.stag(QString("rootfile full-path=\"%1\"").arg(XmlWriter::xmlString(fn)));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
xml.etag();
|
2017-06-02 11:21:01 +02:00
|
|
|
|
for (ImageStoreItem* ip : imageStore) {
|
2012-05-26 14:26:10 +02:00
|
|
|
|
if (!ip->isUsed(this))
|
|
|
|
|
continue;
|
|
|
|
|
QString path = QString("Pictures/") + ip->hashName();
|
|
|
|
|
xml.tag("file", path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xml.etag();
|
|
|
|
|
xml.etag();
|
|
|
|
|
cbuf.seek(0);
|
2013-06-19 09:42:56 +02:00
|
|
|
|
//uz.addDirectory("META-INF");
|
2012-06-04 21:06:12 +02:00
|
|
|
|
uz.addFile("META-INF/container.xml", cbuf.data());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2018-11-29 16:03:07 +01:00
|
|
|
|
QBuffer dbuf;
|
|
|
|
|
dbuf.open(QIODevice::ReadWrite);
|
|
|
|
|
saveFile(&dbuf, true, onlySelection);
|
|
|
|
|
dbuf.seek(0);
|
|
|
|
|
uz.addFile(fn, dbuf.data());
|
|
|
|
|
f->flush(); // flush to preserve score data in case of
|
|
|
|
|
// any failures on the further operations.
|
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
|
// save images
|
2013-06-19 09:42:56 +02:00
|
|
|
|
//uz.addDirectory("Pictures");
|
2019-03-19 11:25:33 +01:00
|
|
|
|
for (ImageStoreItem* ip : imageStore) {
|
2012-05-26 14:26:10 +02:00
|
|
|
|
if (!ip->isUsed(this))
|
|
|
|
|
continue;
|
|
|
|
|
QString path = QString("Pictures/") + ip->hashName();
|
2012-06-23 11:42:40 +02:00
|
|
|
|
uz.addFile(path, ip->buffer());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2014-11-12 15:01:08 +01:00
|
|
|
|
|
|
|
|
|
// create thumbnail
|
2018-08-22 17:06:08 +02:00
|
|
|
|
if (doCreateThumbnail && !pages().isEmpty()) {
|
2017-06-02 11:21:01 +02:00
|
|
|
|
QImage pm = createThumbnail();
|
|
|
|
|
|
|
|
|
|
QByteArray ba;
|
|
|
|
|
QBuffer b(&ba);
|
|
|
|
|
if (!b.open(QIODevice::WriteOnly))
|
|
|
|
|
qDebug("open buffer failed");
|
|
|
|
|
if (!pm.save(&b, "PNG"))
|
|
|
|
|
qDebug("save failed");
|
|
|
|
|
uz.addFile("Thumbnails/thumbnail.png", ba);
|
|
|
|
|
}
|
2014-11-12 15:01:08 +01:00
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
|
#ifdef OMR
|
|
|
|
|
//
|
|
|
|
|
// save OMR page images
|
|
|
|
|
//
|
2015-11-12 16:20:17 +01:00
|
|
|
|
if (masterScore()->omr()) {
|
|
|
|
|
int n = masterScore()->omr()->numPages();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
|
QString path = QString("OmrPages/page%1.png").arg(i+1);
|
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs.
Most warnings are in the following categories:
- Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes)
- Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour.
- Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out.
- (Potentially) uninitialized local variable. Just initialized the vars.
- foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"."
Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types.
- all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h)
- awl/aslider.h: unreachable code.
- awl/knob.cpp: name hiding
- awl/mslider.cpp: name hiding
- awl/slider.cpp: name hiding
- bww2mxml/parser.cpp: name hiding
- effects/compressor/compressor.cpp: narrowing conversion
- effects/zita1/zitagui.cpp: name hiding
- fluid/fluid.cpp: foreach replacement. Name hiding.
- fluid/mod.cpp: name hiding.
- fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars.
- fluid/voice.cpp: Name hiding.
- libmscore/accidental.cpp: Name hiding.
- libmscore/ambitus.cpp: Initialize vars.
- libmscore/barline.cpp: Name hiding. Unreachable code.
- libmscore/beam.cpp: Name hiding.
- libmscore/chordrest.cpp: Unreachable code.
- libmscore/scorefile.cpp: Name hiding.
- manual/genManual.cpp: Name hiding. foreach replacement.
- midi/midifile.cpp: Name hiding. Unreachable code.
- omr/importpdf.cpp: Name hiding. foreach replacement.
- omr/omr.cpp: Name hiding. foreach replacement.
- omr/omrpage.cpp: Name hiding. foreach replacement.
- omr/omrview.cpp: Name hiding. foreach replacement.
- synthesizer/event.cpp: Unreachable code.
- zerberus\channel.cpp: Narrowing conversion.
- zerberus\instrument.cpp: Name hiding.
- zerberus\sfz.cpp: Name hiding.
- zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union"
- zerberus\zerberus.cpp: Name hiding. Unreferenced parameter.
- zerberus\zerberusgui.cpp: Name hiding.
2018-05-03 03:04:08 +02:00
|
|
|
|
QBuffer cbuf1;
|
2015-11-12 16:20:17 +01:00
|
|
|
|
OmrPage* page = masterScore()->omr()->page(i);
|
2013-05-12 12:43:22 +02:00
|
|
|
|
const QImage& image = page->image();
|
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs.
Most warnings are in the following categories:
- Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes)
- Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour.
- Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out.
- (Potentially) uninitialized local variable. Just initialized the vars.
- foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"."
Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types.
- all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h)
- awl/aslider.h: unreachable code.
- awl/knob.cpp: name hiding
- awl/mslider.cpp: name hiding
- awl/slider.cpp: name hiding
- bww2mxml/parser.cpp: name hiding
- effects/compressor/compressor.cpp: narrowing conversion
- effects/zita1/zitagui.cpp: name hiding
- fluid/fluid.cpp: foreach replacement. Name hiding.
- fluid/mod.cpp: name hiding.
- fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars.
- fluid/voice.cpp: Name hiding.
- libmscore/accidental.cpp: Name hiding.
- libmscore/ambitus.cpp: Initialize vars.
- libmscore/barline.cpp: Name hiding. Unreachable code.
- libmscore/beam.cpp: Name hiding.
- libmscore/chordrest.cpp: Unreachable code.
- libmscore/scorefile.cpp: Name hiding.
- manual/genManual.cpp: Name hiding. foreach replacement.
- midi/midifile.cpp: Name hiding. Unreachable code.
- omr/importpdf.cpp: Name hiding. foreach replacement.
- omr/omr.cpp: Name hiding. foreach replacement.
- omr/omrpage.cpp: Name hiding. foreach replacement.
- omr/omrview.cpp: Name hiding. foreach replacement.
- synthesizer/event.cpp: Unreachable code.
- zerberus\channel.cpp: Narrowing conversion.
- zerberus\instrument.cpp: Name hiding.
- zerberus\sfz.cpp: Name hiding.
- zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union"
- zerberus\zerberus.cpp: Name hiding. Unreferenced parameter.
- zerberus\zerberusgui.cpp: Name hiding.
2018-05-03 03:04:08 +02:00
|
|
|
|
if (!image.save(&cbuf1, "PNG")) {
|
2018-11-24 21:08:07 +01:00
|
|
|
|
MScore::lastError = tr("Save file: cannot save image (%1x%2)").arg(image.width(), image.height());
|
2016-09-14 12:08:14 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs.
Most warnings are in the following categories:
- Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes)
- Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour.
- Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out.
- (Potentially) uninitialized local variable. Just initialized the vars.
- foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"."
Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types.
- all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h)
- awl/aslider.h: unreachable code.
- awl/knob.cpp: name hiding
- awl/mslider.cpp: name hiding
- awl/slider.cpp: name hiding
- bww2mxml/parser.cpp: name hiding
- effects/compressor/compressor.cpp: narrowing conversion
- effects/zita1/zitagui.cpp: name hiding
- fluid/fluid.cpp: foreach replacement. Name hiding.
- fluid/mod.cpp: name hiding.
- fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars.
- fluid/voice.cpp: Name hiding.
- libmscore/accidental.cpp: Name hiding.
- libmscore/ambitus.cpp: Initialize vars.
- libmscore/barline.cpp: Name hiding. Unreachable code.
- libmscore/beam.cpp: Name hiding.
- libmscore/chordrest.cpp: Unreachable code.
- libmscore/scorefile.cpp: Name hiding.
- manual/genManual.cpp: Name hiding. foreach replacement.
- midi/midifile.cpp: Name hiding. Unreachable code.
- omr/importpdf.cpp: Name hiding. foreach replacement.
- omr/omr.cpp: Name hiding. foreach replacement.
- omr/omrpage.cpp: Name hiding. foreach replacement.
- omr/omrview.cpp: Name hiding. foreach replacement.
- synthesizer/event.cpp: Unreachable code.
- zerberus\channel.cpp: Narrowing conversion.
- zerberus\instrument.cpp: Name hiding.
- zerberus\sfz.cpp: Name hiding.
- zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union"
- zerberus\zerberus.cpp: Name hiding. Unreferenced parameter.
- zerberus\zerberusgui.cpp: Name hiding.
2018-05-03 03:04:08 +02:00
|
|
|
|
uz.addFile(path, cbuf1.data());
|
|
|
|
|
cbuf1.close();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
//
|
|
|
|
|
// save audio
|
|
|
|
|
//
|
2012-06-23 11:42:40 +02:00
|
|
|
|
if (_audio)
|
|
|
|
|
uz.addFile("audio.ogg", _audio->data());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2012-06-04 21:06:12 +02:00
|
|
|
|
uz.close();
|
2016-09-14 12:08:14 +02:00
|
|
|
|
return true;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// saveFile
|
|
|
|
|
// return true on success
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool Score::saveFile(QFileInfo& info)
|
|
|
|
|
{
|
2018-08-03 01:15:56 +02:00
|
|
|
|
if (readOnly() && info == *masterScore()->fileInfo())
|
|
|
|
|
return false;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
if (info.suffix().isEmpty())
|
|
|
|
|
info.setFile(info.filePath() + ".mscx");
|
|
|
|
|
QFile fp(info.filePath());
|
|
|
|
|
if (!fp.open(QIODevice::WriteOnly)) {
|
2017-08-14 11:48:58 +02:00
|
|
|
|
MScore::lastError = tr("Open File\n%1\nfailed: %2").arg(info.filePath(), strerror(errno));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-18 01:34:37 +02:00
|
|
|
|
saveFile(&fp, false, false);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
fp.close();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// loadStyle
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2019-07-12 10:53:09 +02:00
|
|
|
|
bool Score::loadStyle(const QString& fn, bool ign)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
|
|
|
|
QFile f(fn);
|
|
|
|
|
if (f.open(QIODevice::ReadOnly)) {
|
2017-01-05 11:23:47 +01:00
|
|
|
|
MStyle st = style();
|
2019-07-12 10:53:09 +02:00
|
|
|
|
if (st.load(&f, ign)) {
|
2013-03-18 15:14:05 +01:00
|
|
|
|
undo(new ChangeStyle(this, st));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2013-08-29 20:20:39 +02:00
|
|
|
|
else {
|
2017-08-14 11:48:58 +02:00
|
|
|
|
MScore::lastError = tr("The style file is not compatible with this version of MuseScore.");
|
2013-08-29 20:20:39 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
MScore::lastError = strerror(errno);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// saveStyle
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
bool Score::saveStyle(const QString& name)
|
|
|
|
|
{
|
|
|
|
|
QString ext(".mss");
|
|
|
|
|
QFileInfo info(name);
|
|
|
|
|
|
|
|
|
|
if (info.suffix().isEmpty())
|
|
|
|
|
info.setFile(info.filePath() + ext);
|
|
|
|
|
QFile f(info.filePath());
|
|
|
|
|
if (!f.open(QIODevice::WriteOnly)) {
|
2017-08-14 11:48:58 +02:00
|
|
|
|
MScore::lastError = tr("Open Style File\n%1\nfailed: %2").arg(info.filePath(), strerror(errno));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-19 11:51:21 +01:00
|
|
|
|
XmlWriter xml(this, &f);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
xml.header();
|
|
|
|
|
xml.stag("museScore version=\"" MSC_VERSION "\"");
|
2017-01-05 11:23:47 +01:00
|
|
|
|
style().save(xml, false); // save complete style
|
2012-05-26 14:26:10 +02:00
|
|
|
|
xml.etag();
|
|
|
|
|
if (f.error() != QFile::NoError) {
|
2017-08-14 11:48:58 +02:00
|
|
|
|
MScore::lastError = tr("Write Style failed: %1").arg(f.errorString());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// saveFile
|
|
|
|
|
// return true on success
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
extern QString revision;
|
|
|
|
|
|
2016-09-14 12:08:14 +02:00
|
|
|
|
bool Score::saveFile(QIODevice* f, bool msczFormat, bool onlySelection)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
2016-11-19 11:51:21 +01:00
|
|
|
|
XmlWriter xml(this, f);
|
2016-11-19 10:31:14 +01:00
|
|
|
|
xml.setWriteOmr(msczFormat);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
xml.header();
|
2013-03-28 11:09:31 +01:00
|
|
|
|
if (!MScore::testMode) {
|
2014-11-06 10:44:57 +01:00
|
|
|
|
xml.stag("museScore version=\"" MSC_VERSION "\"");
|
2012-05-26 14:26:10 +02:00
|
|
|
|
xml.tag("programVersion", VERSION);
|
|
|
|
|
xml.tag("programRevision", revision);
|
|
|
|
|
}
|
2017-01-05 11:23:47 +01:00
|
|
|
|
else
|
2018-05-18 01:34:37 +02:00
|
|
|
|
xml.stag("museScore version=\"3.01\"");
|
2017-01-05 11:23:47 +01:00
|
|
|
|
write(xml, onlySelection);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
xml.etag();
|
2016-03-10 10:41:31 +01:00
|
|
|
|
if (isMaster())
|
|
|
|
|
masterScore()->revisions()->write(xml);
|
2014-02-26 19:06:42 +01:00
|
|
|
|
if (!onlySelection) {
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//update version values for i.e. plugin access
|
|
|
|
|
_mscoreVersion = VERSION;
|
2017-04-18 10:00:01 +02:00
|
|
|
|
_mscoreRevision = revision.toInt(0, 16);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
_mscVersion = MSCVERSION;
|
|
|
|
|
}
|
2016-09-14 12:08:14 +02:00
|
|
|
|
return true;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-12 13:05:29 +01:00
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// readRootFile
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
QString readRootFile(MQZipReader* uz, QList<QString>& images)
|
|
|
|
|
{
|
|
|
|
|
QString rootfile;
|
|
|
|
|
|
|
|
|
|
QByteArray cbuf = uz->fileData("META-INF/container.xml");
|
|
|
|
|
if (cbuf.isEmpty()) {
|
|
|
|
|
qDebug("can't find container.xml");
|
|
|
|
|
return rootfile;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-21 13:30:07 +01:00
|
|
|
|
XmlReader e(cbuf);
|
2013-11-12 13:05:29 +01:00
|
|
|
|
|
|
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
|
if (e.name() != "container") {
|
|
|
|
|
e.unknown();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
|
if (e.name() != "rootfiles") {
|
|
|
|
|
e.unknown();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
|
const QStringRef& tag(e.name());
|
|
|
|
|
|
|
|
|
|
if (tag == "rootfile") {
|
2013-11-13 09:17:08 +01:00
|
|
|
|
if (rootfile.isEmpty()) {
|
2013-11-12 13:05:29 +01:00
|
|
|
|
rootfile = e.attribute("full-path");
|
2013-11-13 09:17:08 +01:00
|
|
|
|
e.skipCurrentElement();
|
|
|
|
|
}
|
2013-11-12 13:05:29 +01:00
|
|
|
|
}
|
|
|
|
|
else if (tag == "file")
|
|
|
|
|
images.append(e.readElementText());
|
|
|
|
|
else
|
|
|
|
|
e.unknown();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return rootfile;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-12 15:01:08 +01:00
|
|
|
|
//---------------------------------------------------------
|
2012-05-26 14:26:10 +02:00
|
|
|
|
// loadCompressedMsc
|
|
|
|
|
// return false on error
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
|
Score::FileError MasterScore::loadCompressedMsc(QIODevice* io, bool ignoreVersionError)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
2015-05-19 12:31:28 +02:00
|
|
|
|
MQZipReader uz(io);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2013-11-12 13:05:29 +01:00
|
|
|
|
QList<QString> sl;
|
|
|
|
|
QString rootfile = readRootFile(&uz, sl);
|
2013-01-11 18:10:18 +01:00
|
|
|
|
if (rootfile.isEmpty())
|
2014-05-30 10:17:44 +02:00
|
|
|
|
return FileError::FILE_NO_ROOTFILE;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2013-12-10 17:16:38 +01:00
|
|
|
|
//
|
|
|
|
|
// load images
|
|
|
|
|
//
|
2014-03-04 17:40:23 +01:00
|
|
|
|
if (!MScore::noImages) {
|
|
|
|
|
foreach(const QString& s, sl) {
|
|
|
|
|
QByteArray dbuf = uz.fileData(s);
|
|
|
|
|
imageStore.add(s, dbuf);
|
|
|
|
|
}
|
2013-12-10 17:16:38 +01:00
|
|
|
|
}
|
|
|
|
|
|
2012-06-04 21:06:12 +02:00
|
|
|
|
QByteArray dbuf = uz.fileData(rootfile);
|
2012-06-11 12:15:21 +02:00
|
|
|
|
if (dbuf.isEmpty()) {
|
2018-06-05 20:17:21 +02:00
|
|
|
|
QVector<MQZipReader::FileInfo> fil = uz.fileInfoList();
|
2013-07-26 15:39:46 +02:00
|
|
|
|
foreach(const MQZipReader::FileInfo& fi, fil) {
|
2012-06-23 14:20:03 +02:00
|
|
|
|
if (fi.filePath.endsWith(".mscx")) {
|
2012-06-11 12:15:21 +02:00
|
|
|
|
dbuf = uz.fileData(fi.filePath);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-02-21 13:30:07 +01:00
|
|
|
|
XmlReader e(dbuf);
|
2018-12-12 17:28:59 +01:00
|
|
|
|
QBuffer readAheadBuf(&dbuf);
|
|
|
|
|
e.setReadAheadDevice(&readAheadBuf);
|
2016-03-10 10:41:31 +01:00
|
|
|
|
e.setDocName(masterScore()->fileInfo()->completeBaseName());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
|
FileError retval = read1(e, ignoreVersionError);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
|
|
#ifdef OMR
|
|
|
|
|
//
|
|
|
|
|
// load OMR page images
|
|
|
|
|
//
|
2015-11-12 16:20:17 +01:00
|
|
|
|
if (masterScore()->omr()) {
|
|
|
|
|
int n = masterScore()->omr()->numPages();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
|
QString path = QString("OmrPages/page%1.png").arg(i+1);
|
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs.
Most warnings are in the following categories:
- Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes)
- Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour.
- Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out.
- (Potentially) uninitialized local variable. Just initialized the vars.
- foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"."
Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types.
- all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h)
- awl/aslider.h: unreachable code.
- awl/knob.cpp: name hiding
- awl/mslider.cpp: name hiding
- awl/slider.cpp: name hiding
- bww2mxml/parser.cpp: name hiding
- effects/compressor/compressor.cpp: narrowing conversion
- effects/zita1/zitagui.cpp: name hiding
- fluid/fluid.cpp: foreach replacement. Name hiding.
- fluid/mod.cpp: name hiding.
- fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars.
- fluid/voice.cpp: Name hiding.
- libmscore/accidental.cpp: Name hiding.
- libmscore/ambitus.cpp: Initialize vars.
- libmscore/barline.cpp: Name hiding. Unreachable code.
- libmscore/beam.cpp: Name hiding.
- libmscore/chordrest.cpp: Unreachable code.
- libmscore/scorefile.cpp: Name hiding.
- manual/genManual.cpp: Name hiding. foreach replacement.
- midi/midifile.cpp: Name hiding. Unreachable code.
- omr/importpdf.cpp: Name hiding. foreach replacement.
- omr/omr.cpp: Name hiding. foreach replacement.
- omr/omrpage.cpp: Name hiding. foreach replacement.
- omr/omrview.cpp: Name hiding. foreach replacement.
- synthesizer/event.cpp: Unreachable code.
- zerberus\channel.cpp: Narrowing conversion.
- zerberus\instrument.cpp: Name hiding.
- zerberus\sfz.cpp: Name hiding.
- zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union"
- zerberus\zerberus.cpp: Name hiding. Unreferenced parameter.
- zerberus\zerberusgui.cpp: Name hiding.
2018-05-03 03:04:08 +02:00
|
|
|
|
QByteArray dbuf1 = uz.fileData(path);
|
2015-11-12 16:20:17 +01:00
|
|
|
|
OmrPage* page = masterScore()->omr()->page(i);
|
2012-06-04 21:06:12 +02:00
|
|
|
|
QImage image;
|
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs.
Most warnings are in the following categories:
- Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes)
- Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour.
- Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out.
- (Potentially) uninitialized local variable. Just initialized the vars.
- foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"."
Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types.
- all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h)
- awl/aslider.h: unreachable code.
- awl/knob.cpp: name hiding
- awl/mslider.cpp: name hiding
- awl/slider.cpp: name hiding
- bww2mxml/parser.cpp: name hiding
- effects/compressor/compressor.cpp: narrowing conversion
- effects/zita1/zitagui.cpp: name hiding
- fluid/fluid.cpp: foreach replacement. Name hiding.
- fluid/mod.cpp: name hiding.
- fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars.
- fluid/voice.cpp: Name hiding.
- libmscore/accidental.cpp: Name hiding.
- libmscore/ambitus.cpp: Initialize vars.
- libmscore/barline.cpp: Name hiding. Unreachable code.
- libmscore/beam.cpp: Name hiding.
- libmscore/chordrest.cpp: Unreachable code.
- libmscore/scorefile.cpp: Name hiding.
- manual/genManual.cpp: Name hiding. foreach replacement.
- midi/midifile.cpp: Name hiding. Unreachable code.
- omr/importpdf.cpp: Name hiding. foreach replacement.
- omr/omr.cpp: Name hiding. foreach replacement.
- omr/omrpage.cpp: Name hiding. foreach replacement.
- omr/omrview.cpp: Name hiding. foreach replacement.
- synthesizer/event.cpp: Unreachable code.
- zerberus\channel.cpp: Narrowing conversion.
- zerberus\instrument.cpp: Name hiding.
- zerberus\sfz.cpp: Name hiding.
- zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union"
- zerberus\zerberus.cpp: Name hiding. Unreferenced parameter.
- zerberus\zerberusgui.cpp: Name hiding.
2018-05-03 03:04:08 +02:00
|
|
|
|
if (image.loadFromData(dbuf1, "PNG")) {
|
2012-06-04 21:06:12 +02:00
|
|
|
|
page->setImage(image);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2012-06-04 21:06:12 +02:00
|
|
|
|
else
|
|
|
|
|
qDebug("load image failed");
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
//
|
|
|
|
|
// read audio
|
|
|
|
|
//
|
2016-03-10 10:41:31 +01:00
|
|
|
|
if (audio()) {
|
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs.
Most warnings are in the following categories:
- Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes)
- Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour.
- Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out.
- (Potentially) uninitialized local variable. Just initialized the vars.
- foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"."
Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types.
- all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h)
- awl/aslider.h: unreachable code.
- awl/knob.cpp: name hiding
- awl/mslider.cpp: name hiding
- awl/slider.cpp: name hiding
- bww2mxml/parser.cpp: name hiding
- effects/compressor/compressor.cpp: narrowing conversion
- effects/zita1/zitagui.cpp: name hiding
- fluid/fluid.cpp: foreach replacement. Name hiding.
- fluid/mod.cpp: name hiding.
- fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars.
- fluid/voice.cpp: Name hiding.
- libmscore/accidental.cpp: Name hiding.
- libmscore/ambitus.cpp: Initialize vars.
- libmscore/barline.cpp: Name hiding. Unreachable code.
- libmscore/beam.cpp: Name hiding.
- libmscore/chordrest.cpp: Unreachable code.
- libmscore/scorefile.cpp: Name hiding.
- manual/genManual.cpp: Name hiding. foreach replacement.
- midi/midifile.cpp: Name hiding. Unreachable code.
- omr/importpdf.cpp: Name hiding. foreach replacement.
- omr/omr.cpp: Name hiding. foreach replacement.
- omr/omrpage.cpp: Name hiding. foreach replacement.
- omr/omrview.cpp: Name hiding. foreach replacement.
- synthesizer/event.cpp: Unreachable code.
- zerberus\channel.cpp: Narrowing conversion.
- zerberus\instrument.cpp: Name hiding.
- zerberus\sfz.cpp: Name hiding.
- zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union"
- zerberus\zerberus.cpp: Name hiding. Unreferenced parameter.
- zerberus\zerberusgui.cpp: Name hiding.
2018-05-03 03:04:08 +02:00
|
|
|
|
QByteArray dbuf1 = uz.fileData("audio.ogg");
|
|
|
|
|
audio()->setData(dbuf1);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// loadMsc
|
|
|
|
|
// return true on success
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
|
Score::FileError MasterScore::loadMsc(QString name, bool ignoreVersionError)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
|
|
|
|
QFile f(name);
|
|
|
|
|
if (!f.open(QIODevice::ReadOnly)) {
|
|
|
|
|
MScore::lastError = f.errorString();
|
2014-05-30 10:17:44 +02:00
|
|
|
|
return FileError::FILE_OPEN_ERROR;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2016-12-31 13:44:32 +01:00
|
|
|
|
return loadMsc(name, &f, ignoreVersionError);
|
2015-05-19 12:31:28 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
|
Score::FileError MasterScore::loadMsc(QString name, QIODevice* io, bool ignoreVersionError)
|
2015-05-19 12:31:28 +02:00
|
|
|
|
{
|
2018-11-08 15:45:14 +01:00
|
|
|
|
ScoreLoad sl;
|
2016-03-10 10:41:31 +01:00
|
|
|
|
fileInfo()->setFile(name);
|
2015-05-19 12:31:28 +02:00
|
|
|
|
|
|
|
|
|
if (name.endsWith(".mscz"))
|
|
|
|
|
return loadCompressedMsc(io, ignoreVersionError);
|
|
|
|
|
else {
|
2018-02-21 13:30:07 +01:00
|
|
|
|
XmlReader r(io);
|
2018-12-12 17:28:59 +01:00
|
|
|
|
r.setReadAheadDevice(io);
|
2015-05-19 12:31:28 +02:00
|
|
|
|
return read1(r, ignoreVersionError);
|
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// parseVersion
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
|
void MasterScore::parseVersion(const QString& val)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
|
|
|
|
QRegExp re("(\\d+)\\.(\\d+)\\.(\\d+)");
|
|
|
|
|
int v1, v2, v3, rv1, rv2, rv3;
|
|
|
|
|
if (re.indexIn(VERSION) != -1) {
|
|
|
|
|
QStringList sl = re.capturedTexts();
|
|
|
|
|
if (sl.size() == 4) {
|
|
|
|
|
v1 = sl[1].toInt();
|
|
|
|
|
v2 = sl[2].toInt();
|
|
|
|
|
v3 = sl[3].toInt();
|
|
|
|
|
if (re.indexIn(val) != -1) {
|
|
|
|
|
sl = re.capturedTexts();
|
|
|
|
|
if (sl.size() == 4) {
|
|
|
|
|
rv1 = sl[1].toInt();
|
|
|
|
|
rv2 = sl[2].toInt();
|
|
|
|
|
rv3 = sl[3].toInt();
|
|
|
|
|
|
|
|
|
|
int currentVersion = v1 * 10000 + v2 * 100 + v3;
|
|
|
|
|
int readVersion = rv1 * 10000 + rv2 * 100 + rv3;
|
|
|
|
|
if (readVersion > currentVersion) {
|
2014-03-25 13:33:47 +01:00
|
|
|
|
qDebug("read future version");
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
QRegExp re1("(\\d+)\\.(\\d+)");
|
|
|
|
|
if (re1.indexIn(val) != -1) {
|
|
|
|
|
sl = re.capturedTexts();
|
|
|
|
|
if (sl.size() == 3) {
|
|
|
|
|
rv1 = sl[1].toInt();
|
|
|
|
|
rv2 = sl[2].toInt();
|
|
|
|
|
|
|
|
|
|
int currentVersion = v1 * 10000 + v2 * 100 + v3;
|
|
|
|
|
int readVersion = rv1 * 10000 + rv2 * 100;
|
|
|
|
|
if (readVersion > currentVersion) {
|
2014-03-25 13:33:47 +01:00
|
|
|
|
qDebug("read future version");
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2014-03-25 13:33:47 +01:00
|
|
|
|
qDebug("1cannot parse <%s>", qPrintable(val));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2014-03-25 13:33:47 +01:00
|
|
|
|
qDebug("2cannot parse <%s>", VERSION);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// read1
|
|
|
|
|
// return true on success
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
|
Score::FileError MasterScore::read1(XmlReader& e, bool ignoreVersionError)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
2013-01-11 18:10:18 +01:00
|
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
|
if (e.name() == "museScore") {
|
2012-05-26 14:26:10 +02:00
|
|
|
|
const QString& version = e.attribute("version");
|
|
|
|
|
QStringList sl = version.split('.');
|
2016-03-10 10:41:31 +01:00
|
|
|
|
setMscVersion(sl[0].toInt() * 100 + sl[1].toInt());
|
2012-09-14 17:34:31 +02:00
|
|
|
|
|
2012-09-29 16:46:45 +02:00
|
|
|
|
if (!ignoreVersionError) {
|
|
|
|
|
QString message;
|
2016-03-10 10:41:31 +01:00
|
|
|
|
if (mscVersion() > MSCVERSION)
|
2014-05-30 10:17:44 +02:00
|
|
|
|
return FileError::FILE_TOO_NEW;
|
2016-09-13 09:39:50 +02:00
|
|
|
|
if (mscVersion() < 114)
|
2014-05-30 10:17:44 +02:00
|
|
|
|
return FileError::FILE_TOO_OLD;
|
2018-09-02 15:30:28 +02:00
|
|
|
|
if (mscVersion() == 300)
|
|
|
|
|
return FileError::FILE_OLD_300_FORMAT;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2016-09-29 17:46:26 +02:00
|
|
|
|
Score::FileError error;
|
2017-08-16 10:53:03 +02:00
|
|
|
|
if (mscVersion() <= 114)
|
2016-09-29 17:46:26 +02:00
|
|
|
|
error = read114(e);
|
2017-09-05 10:43:22 +02:00
|
|
|
|
else if (mscVersion() <= 207)
|
2016-09-29 17:46:26 +02:00
|
|
|
|
error = read206(e);
|
|
|
|
|
else
|
2018-05-18 01:34:37 +02:00
|
|
|
|
error = read301(e);
|
2016-09-29 17:46:26 +02:00
|
|
|
|
setExcerptsChanged(false);
|
|
|
|
|
return error;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
2013-01-11 18:10:18 +01:00
|
|
|
|
e.unknown();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2016-09-13 09:39:50 +02:00
|
|
|
|
return FileError::FILE_CORRUPTED;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// print
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void Score::print(QPainter* painter, int pageNo)
|
|
|
|
|
{
|
|
|
|
|
_printing = true;
|
2015-05-13 13:25:44 +02:00
|
|
|
|
MScore::pdfPrinting = true;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
Page* page = pages().at(pageNo);
|
|
|
|
|
QRectF fr = page->abbox();
|
|
|
|
|
|
2013-04-29 15:31:22 +02:00
|
|
|
|
QList<Element*> ell = page->items(fr);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
qStableSort(ell.begin(), ell.end(), elementLessThan);
|
2016-09-26 12:02:05 +02:00
|
|
|
|
for (const Element* e : ell) {
|
2012-05-26 14:26:10 +02:00
|
|
|
|
if (!e->visible())
|
|
|
|
|
continue;
|
|
|
|
|
painter->save();
|
|
|
|
|
painter->translate(e->pagePos());
|
|
|
|
|
e->draw(painter);
|
|
|
|
|
painter->restore();
|
|
|
|
|
}
|
2015-05-13 13:25:44 +02:00
|
|
|
|
MScore::pdfPrinting = false;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
_printing = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// readCompressedToBuffer
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
|
QByteArray MasterScore::readCompressedToBuffer()
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
2014-12-08 14:41:36 +01:00
|
|
|
|
MQZipReader uz(info.filePath());
|
2014-11-12 18:57:15 +01:00
|
|
|
|
if (!uz.exists()) {
|
|
|
|
|
qDebug("Score::readCompressedToBuffer: cannot read zip file");
|
|
|
|
|
return QByteArray();
|
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
QList<QString> images;
|
2013-11-12 13:05:29 +01:00
|
|
|
|
QString rootfile = readRootFile(&uz, images);
|
2013-01-11 18:10:18 +01:00
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//
|
|
|
|
|
// load images
|
|
|
|
|
//
|
|
|
|
|
foreach(const QString& s, images) {
|
2012-06-04 21:06:12 +02:00
|
|
|
|
QByteArray dbuf = uz.fileData(s);
|
|
|
|
|
imageStore.add(s, dbuf);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rootfile.isEmpty()) {
|
2014-12-08 14:41:36 +01:00
|
|
|
|
qDebug("=can't find rootfile in: %s", qPrintable(info.filePath()));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
return QByteArray();
|
|
|
|
|
}
|
2012-06-04 21:06:12 +02:00
|
|
|
|
return uz.fileData(rootfile);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// readToBuffer
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
|
QByteArray MasterScore::readToBuffer()
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
|
|
|
|
QByteArray ba;
|
|
|
|
|
QString cs = info.suffix();
|
|
|
|
|
|
|
|
|
|
if (cs == "mscz") {
|
|
|
|
|
ba = readCompressedToBuffer();
|
|
|
|
|
}
|
|
|
|
|
if (cs.toLower() == "msc" || cs.toLower() == "mscx") {
|
2014-12-08 14:41:36 +01:00
|
|
|
|
QFile f(info.filePath());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
if (f.open(QIODevice::ReadOnly)) {
|
|
|
|
|
ba = f.readAll();
|
|
|
|
|
f.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ba;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// createRevision
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void Score::createRevision()
|
|
|
|
|
{
|
|
|
|
|
#if 0
|
2014-03-25 13:33:47 +01:00
|
|
|
|
qDebug("createRevision");
|
2012-05-26 14:26:10 +02:00
|
|
|
|
QBuffer dbuf;
|
|
|
|
|
dbuf.open(QIODevice::ReadWrite);
|
|
|
|
|
saveFile(&dbuf, false, false);
|
|
|
|
|
dbuf.close();
|
|
|
|
|
|
|
|
|
|
QByteArray ba1 = readToBuffer();
|
|
|
|
|
|
|
|
|
|
QString os = QString::fromUtf8(ba1.data(), ba1.size());
|
|
|
|
|
QString ns = QString::fromUtf8(dbuf.buffer().data(), dbuf.buffer().size());
|
|
|
|
|
|
|
|
|
|
diff_match_patch dmp;
|
|
|
|
|
Revision* r = new Revision();
|
|
|
|
|
r->setDiff(dmp.patch_toText(dmp.patch_make(ns, os)));
|
|
|
|
|
r->setId("1");
|
|
|
|
|
_revisions->add(r);
|
|
|
|
|
|
2014-03-25 13:33:47 +01:00
|
|
|
|
// qDebug("patch:\n%s\n==========", qPrintable(patch));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-14 23:15:43 +02:00
|
|
|
|
//---------------------------------------------------------
|
2018-08-15 00:25:30 +02:00
|
|
|
|
// writeVoiceMove
|
|
|
|
|
// write <move> and starting <voice> tags to denote
|
|
|
|
|
// change in position.
|
|
|
|
|
// Returns true if <voice> tag was written.
|
2018-08-14 23:15:43 +02:00
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2019-01-30 15:13:54 +01:00
|
|
|
|
static bool writeVoiceMove(XmlWriter& xml, Segment* seg, const Fraction& startTick, int track, int* lastTrackWrittenPtr)
|
2018-08-14 23:15:43 +02:00
|
|
|
|
{
|
|
|
|
|
bool voiceTagWritten = false;
|
2018-12-07 16:25:31 +01:00
|
|
|
|
int& lastTrackWritten = *lastTrackWrittenPtr;
|
2018-08-14 23:15:43 +02:00
|
|
|
|
if ((lastTrackWritten < track) && !xml.clipboardmode()) {
|
|
|
|
|
while (lastTrackWritten < (track - 1)) {
|
|
|
|
|
xml.tagE("voice");
|
|
|
|
|
++lastTrackWritten;
|
|
|
|
|
}
|
|
|
|
|
xml.stag("voice");
|
|
|
|
|
xml.setCurTick(startTick);
|
|
|
|
|
xml.setCurTrack(track);
|
2018-12-07 16:25:31 +01:00
|
|
|
|
++lastTrackWritten;
|
2018-08-14 23:15:43 +02:00
|
|
|
|
voiceTagWritten = true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-30 15:13:54 +01:00
|
|
|
|
if ((xml.curTick() != seg->tick()) || (track != xml.curTrack())) {
|
2018-08-14 23:15:43 +02:00
|
|
|
|
Location curr = Location::absolute();
|
|
|
|
|
Location dest = Location::absolute();
|
2019-01-30 15:13:54 +01:00
|
|
|
|
curr.setFrac(xml.curTick());
|
|
|
|
|
dest.setFrac(seg->tick());
|
2018-08-14 23:15:43 +02:00
|
|
|
|
curr.setTrack(xml.curTrack());
|
|
|
|
|
dest.setTrack(track);
|
|
|
|
|
|
|
|
|
|
dest.toRelative(curr);
|
|
|
|
|
dest.write(xml);
|
|
|
|
|
|
|
|
|
|
xml.setCurTick(seg->tick());
|
|
|
|
|
xml.setCurTrack(track);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return voiceTagWritten;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// writeSegments
|
2013-01-07 15:39:28 +01:00
|
|
|
|
// ls - write upto this segment (excluding)
|
|
|
|
|
// can be zero
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2016-11-19 11:51:21 +01:00
|
|
|
|
void Score::writeSegments(XmlWriter& xml, int strack, int etrack,
|
2019-07-01 00:29:25 +02:00
|
|
|
|
Segment* sseg, Segment* eseg, bool writeSystemElements, bool forceTimeSig)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
2019-01-30 15:13:54 +01:00
|
|
|
|
Fraction startTick = xml.curTick();
|
2019-07-01 00:29:25 +02:00
|
|
|
|
Fraction endTick = eseg ? eseg->tick() : lastMeasure()->endTick();
|
2019-01-30 15:13:54 +01:00
|
|
|
|
bool clip = xml.clipboardmode();
|
|
|
|
|
|
2015-08-29 00:10:07 +02:00
|
|
|
|
// in clipboard mode, ls might be in an mmrest
|
|
|
|
|
// since we are traversing regular measures,
|
2016-12-06 09:52:24 +01:00
|
|
|
|
// force them out of mmRest
|
|
|
|
|
if (clip) {
|
2019-07-01 00:29:25 +02:00
|
|
|
|
Measure* lm = eseg ? eseg->measure() : 0;
|
|
|
|
|
Measure* fm = sseg ? sseg->measure() : 0;
|
2016-12-06 09:52:24 +01:00
|
|
|
|
if (lm && lm->isMMRest()) {
|
|
|
|
|
lm = lm->mmRestLast();
|
|
|
|
|
if (lm)
|
2019-07-01 00:29:25 +02:00
|
|
|
|
eseg = lm->nextMeasure() ? lm->nextMeasure()->first() : nullptr;
|
2016-12-06 09:52:24 +01:00
|
|
|
|
else
|
|
|
|
|
qDebug("writeSegments: no measure for end segment in mmrest");
|
|
|
|
|
}
|
|
|
|
|
if (fm && fm->isMMRest()) {
|
|
|
|
|
fm = fm->mmRestFirst();
|
|
|
|
|
if (fm)
|
2019-07-01 00:29:25 +02:00
|
|
|
|
sseg = fm->first();
|
2016-12-06 09:52:24 +01:00
|
|
|
|
}
|
2015-08-29 00:10:07 +02:00
|
|
|
|
}
|
2017-06-02 18:25:04 +02:00
|
|
|
|
|
|
|
|
|
QList<Spanner*> spanners;
|
|
|
|
|
#if 0
|
|
|
|
|
auto endIt = spanner().upper_bound(endTick);
|
|
|
|
|
for (auto i = spanner().begin(); i != endIt; ++i) {
|
|
|
|
|
Spanner* s = i->second;
|
|
|
|
|
#else
|
2019-07-01 00:29:25 +02:00
|
|
|
|
auto sl = spannerMap().findOverlapping(sseg->tick().ticks(), endTick.ticks());
|
2017-06-02 18:25:04 +02:00
|
|
|
|
for (auto i : sl) {
|
|
|
|
|
Spanner* s = i.value;
|
|
|
|
|
#endif
|
|
|
|
|
if (s->generated() || !xml.canWrite(s))
|
|
|
|
|
continue;
|
|
|
|
|
// don't write voltas to clipboard
|
|
|
|
|
if (clip && s->isVolta())
|
|
|
|
|
continue;
|
|
|
|
|
spanners.push_back(s);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-15 00:25:30 +02:00
|
|
|
|
int lastTrackWritten = strack - 1; // for counting necessary <voice> tags
|
2012-05-26 14:26:10 +02:00
|
|
|
|
for (int track = strack; track < etrack; ++track) {
|
2014-08-12 20:10:46 +02:00
|
|
|
|
if (!xml.canWriteVoice(track))
|
|
|
|
|
continue;
|
2017-03-09 23:55:10 +01:00
|
|
|
|
|
2018-08-15 00:25:30 +02:00
|
|
|
|
bool voiceTagWritten = false;
|
|
|
|
|
|
2017-03-09 23:55:10 +01:00
|
|
|
|
bool timeSigWritten = false; // for forceTimeSig
|
|
|
|
|
bool crWritten = false; // for forceTimeSig
|
|
|
|
|
bool keySigWritten = false; // for forceTimeSig
|
|
|
|
|
|
2019-07-01 00:29:25 +02:00
|
|
|
|
for (Segment* segment = sseg; segment && segment != eseg; segment = segment->next1()) {
|
2016-10-20 11:32:07 +02:00
|
|
|
|
if (!segment->enabled())
|
|
|
|
|
continue;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
if (track == 0)
|
|
|
|
|
segment->setWritten(false);
|
|
|
|
|
Element* e = segment->element(track);
|
2018-08-15 00:25:30 +02:00
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//
|
|
|
|
|
// special case: - barline span > 1
|
|
|
|
|
// - part (excerpt) staff starts after
|
|
|
|
|
// barline element
|
2018-06-25 02:51:17 +02:00
|
|
|
|
bool needMove = (segment->tick() != xml.curTick() || (track > lastTrackWritten));
|
2016-10-25 17:30:55 +02:00
|
|
|
|
if ((segment->isEndBarLineType()) && !e && writeSystemElements && ((track % VOICES) == 0)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
|
// search barline:
|
|
|
|
|
for (int idx = track - VOICES; idx >= 0; idx -= VOICES) {
|
|
|
|
|
if (segment->element(idx)) {
|
2016-11-19 10:31:14 +01:00
|
|
|
|
int oDiff = xml.trackDiff();
|
|
|
|
|
xml.setTrackDiff(idx); // staffIdx should be zero
|
2012-05-26 14:26:10 +02:00
|
|
|
|
segment->element(idx)->write(xml);
|
2016-11-19 10:31:14 +01:00
|
|
|
|
xml.setTrackDiff(oDiff);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs.
Most warnings are in the following categories:
- Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes)
- Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour.
- Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out.
- (Potentially) uninitialized local variable. Just initialized the vars.
- foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"."
Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types.
- all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h)
- awl/aslider.h: unreachable code.
- awl/knob.cpp: name hiding
- awl/mslider.cpp: name hiding
- awl/slider.cpp: name hiding
- bww2mxml/parser.cpp: name hiding
- effects/compressor/compressor.cpp: narrowing conversion
- effects/zita1/zitagui.cpp: name hiding
- fluid/fluid.cpp: foreach replacement. Name hiding.
- fluid/mod.cpp: name hiding.
- fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars.
- fluid/voice.cpp: Name hiding.
- libmscore/accidental.cpp: Name hiding.
- libmscore/ambitus.cpp: Initialize vars.
- libmscore/barline.cpp: Name hiding. Unreachable code.
- libmscore/beam.cpp: Name hiding.
- libmscore/chordrest.cpp: Unreachable code.
- libmscore/scorefile.cpp: Name hiding.
- manual/genManual.cpp: Name hiding. foreach replacement.
- midi/midifile.cpp: Name hiding. Unreachable code.
- omr/importpdf.cpp: Name hiding. foreach replacement.
- omr/omr.cpp: Name hiding. foreach replacement.
- omr/omrpage.cpp: Name hiding. foreach replacement.
- omr/omrview.cpp: Name hiding. foreach replacement.
- synthesizer/event.cpp: Unreachable code.
- zerberus\channel.cpp: Narrowing conversion.
- zerberus\instrument.cpp: Name hiding.
- zerberus\sfz.cpp: Name hiding.
- zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union"
- zerberus\zerberus.cpp: Name hiding. Unreferenced parameter.
- zerberus\zerberusgui.cpp: Name hiding.
2018-05-03 03:04:08 +02:00
|
|
|
|
for (Element* e1 : segment->annotations()) {
|
|
|
|
|
if (e1->track() != track || e1->generated() || (e1->systemFlag() && !writeSystemElements))
|
2014-07-09 18:05:58 +02:00
|
|
|
|
continue;
|
2018-08-15 00:25:30 +02:00
|
|
|
|
if (needMove) {
|
2018-12-07 16:25:31 +01:00
|
|
|
|
voiceTagWritten |= writeVoiceMove(xml, segment, startTick, track, &lastTrackWritten);
|
2018-08-15 00:25:30 +02:00
|
|
|
|
needMove = false;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
This commit contains changes required for MuseScore to compile under MSVC with no warnings.
MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs.
Most warnings are in the following categories:
- Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes)
- Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour.
- Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out.
- (Potentially) uninitialized local variable. Just initialized the vars.
- foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"."
Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types.
- all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h)
- awl/aslider.h: unreachable code.
- awl/knob.cpp: name hiding
- awl/mslider.cpp: name hiding
- awl/slider.cpp: name hiding
- bww2mxml/parser.cpp: name hiding
- effects/compressor/compressor.cpp: narrowing conversion
- effects/zita1/zitagui.cpp: name hiding
- fluid/fluid.cpp: foreach replacement. Name hiding.
- fluid/mod.cpp: name hiding.
- fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars.
- fluid/voice.cpp: Name hiding.
- libmscore/accidental.cpp: Name hiding.
- libmscore/ambitus.cpp: Initialize vars.
- libmscore/barline.cpp: Name hiding. Unreachable code.
- libmscore/beam.cpp: Name hiding.
- libmscore/chordrest.cpp: Unreachable code.
- libmscore/scorefile.cpp: Name hiding.
- manual/genManual.cpp: Name hiding. foreach replacement.
- midi/midifile.cpp: Name hiding. Unreachable code.
- omr/importpdf.cpp: Name hiding. foreach replacement.
- omr/omr.cpp: Name hiding. foreach replacement.
- omr/omrpage.cpp: Name hiding. foreach replacement.
- omr/omrview.cpp: Name hiding. foreach replacement.
- synthesizer/event.cpp: Unreachable code.
- zerberus\channel.cpp: Narrowing conversion.
- zerberus\instrument.cpp: Name hiding.
- zerberus\sfz.cpp: Name hiding.
- zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union"
- zerberus\zerberus.cpp: Name hiding. Unreferenced parameter.
- zerberus\zerberusgui.cpp: Name hiding.
2018-05-03 03:04:08 +02:00
|
|
|
|
e1->write(xml);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2014-04-24 17:09:42 +02:00
|
|
|
|
Measure* m = segment->measure();
|
2014-04-25 10:37:34 +02:00
|
|
|
|
// don't write spanners for multi measure rests
|
2014-12-29 21:13:11 +01:00
|
|
|
|
|
2017-06-02 18:25:04 +02:00
|
|
|
|
if ((!(m && m->isMMRest())) && segment->isChordRestType()) {
|
|
|
|
|
for (Spanner* s : spanners) {
|
2013-10-13 11:36:08 +02:00
|
|
|
|
if (s->track() == track) {
|
2014-08-20 16:53:26 +02:00
|
|
|
|
bool end = false;
|
|
|
|
|
if (s->anchor() == Spanner::Anchor::CHORD || s->anchor() == Spanner::Anchor::NOTE)
|
|
|
|
|
end = s->tick2() < endTick;
|
|
|
|
|
else
|
|
|
|
|
end = s->tick2() <= endTick;
|
2018-05-23 23:27:23 +02:00
|
|
|
|
if (s->tick() == segment->tick() && (!clip || end) && !s->isSlur()) {
|
2018-08-15 00:25:30 +02:00
|
|
|
|
if (needMove) {
|
2018-12-07 16:25:31 +01:00
|
|
|
|
voiceTagWritten |= writeVoiceMove(xml, segment, startTick, track, &lastTrackWritten);
|
2018-08-15 00:25:30 +02:00
|
|
|
|
needMove = false;
|
2013-10-13 11:36:08 +02:00
|
|
|
|
}
|
2018-05-23 23:27:23 +02:00
|
|
|
|
s->writeSpannerStart(xml, segment, track);
|
2013-06-10 11:03:34 +02:00
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2014-08-12 20:10:46 +02:00
|
|
|
|
if ((s->tick2() == segment->tick())
|
2016-04-11 15:28:32 +02:00
|
|
|
|
&& !s->isSlur()
|
2019-11-22 15:17:51 +01:00
|
|
|
|
&& (s->effectiveTrack2() == track)
|
2019-07-01 00:29:25 +02:00
|
|
|
|
&& (!clip || s->tick() >= sseg->tick())
|
2014-07-03 15:02:36 +02:00
|
|
|
|
) {
|
2018-08-15 00:25:30 +02:00
|
|
|
|
if (needMove) {
|
2018-12-07 16:25:31 +01:00
|
|
|
|
voiceTagWritten |= writeVoiceMove(xml, segment, startTick, track, &lastTrackWritten);
|
2018-08-15 00:25:30 +02:00
|
|
|
|
needMove = false;
|
2013-06-10 11:03:34 +02:00
|
|
|
|
}
|
2018-05-23 23:27:23 +02:00
|
|
|
|
s->writeSpannerEnd(xml, segment, track);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-06-10 11:03:34 +02:00
|
|
|
|
|
2014-06-30 20:24:43 +02:00
|
|
|
|
if (!e || !xml.canWrite(e))
|
2012-05-26 14:26:10 +02:00
|
|
|
|
continue;
|
2016-07-07 16:20:16 +02:00
|
|
|
|
if (e->generated())
|
2012-05-26 14:26:10 +02:00
|
|
|
|
continue;
|
2017-03-09 23:55:10 +01:00
|
|
|
|
if (forceTimeSig && track2voice(track) == 0 && segment->segmentType() == SegmentType::ChordRest && !timeSigWritten && !crWritten) {
|
2018-12-19 17:24:46 +01:00
|
|
|
|
// Ensure that <voice> tag is open
|
|
|
|
|
voiceTagWritten |= writeVoiceMove(xml, segment, startTick, track, &lastTrackWritten);
|
2017-03-09 23:55:10 +01:00
|
|
|
|
// we will miss a key sig!
|
|
|
|
|
if (!keySigWritten) {
|
|
|
|
|
Key k = score()->staff(track2staff(track))->key(segment->tick());
|
|
|
|
|
KeySig* ks = new KeySig(this);
|
|
|
|
|
ks->setKey(k);
|
|
|
|
|
ks->write(xml);
|
|
|
|
|
delete ks;
|
|
|
|
|
keySigWritten = true;
|
|
|
|
|
}
|
|
|
|
|
// we will miss a time sig!
|
|
|
|
|
Fraction tsf = sigmap()->timesig(segment->tick()).timesig();
|
|
|
|
|
TimeSig* ts = new TimeSig(this);
|
|
|
|
|
ts->setSig(tsf);
|
|
|
|
|
ts->write(xml);
|
|
|
|
|
delete ts;
|
|
|
|
|
timeSigWritten = true;
|
|
|
|
|
}
|
2018-08-15 00:25:30 +02:00
|
|
|
|
if (needMove) {
|
2018-12-07 16:25:31 +01:00
|
|
|
|
voiceTagWritten |= writeVoiceMove(xml, segment, startTick, track, &lastTrackWritten);
|
2018-08-15 00:25:30 +02:00
|
|
|
|
needMove = false;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
if (e->isChordRest()) {
|
2016-07-07 16:20:16 +02:00
|
|
|
|
ChordRest* cr = toChordRest(e);
|
2018-06-09 06:19:36 +02:00
|
|
|
|
cr->writeTupletStart(xml);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2016-03-02 13:20:19 +01:00
|
|
|
|
// if (segment->isEndBarLine() && (m->mmRestCount() < 0 || m->mmRest())) {
|
2016-07-07 16:20:16 +02:00
|
|
|
|
// BarLine* bl = toBarLine(e);
|
2016-01-04 14:48:58 +01:00
|
|
|
|
//TODO bl->setBarLineType(m->endBarLineType());
|
|
|
|
|
// bl->setVisible(m->endBarLineVisible());
|
2016-03-02 13:20:19 +01:00
|
|
|
|
// }
|
2013-09-19 15:08:54 +02:00
|
|
|
|
e->write(xml);
|
2018-06-09 06:19:36 +02:00
|
|
|
|
|
|
|
|
|
if (e->isChordRest()) {
|
|
|
|
|
ChordRest* cr = toChordRest(e);
|
|
|
|
|
cr->writeTupletEnd(xml);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-21 15:55:31 +02:00
|
|
|
|
if (!(e->isRest() && toRest(e)->isGap()))
|
|
|
|
|
segment->write(xml); // write only once
|
2017-03-09 23:55:10 +01:00
|
|
|
|
if (forceTimeSig) {
|
|
|
|
|
if (segment->segmentType() == SegmentType::KeySig)
|
|
|
|
|
keySigWritten = true;
|
|
|
|
|
if (segment->segmentType() == SegmentType::TimeSig)
|
|
|
|
|
timeSigWritten = true;
|
|
|
|
|
if (segment->segmentType() == SegmentType::ChordRest)
|
|
|
|
|
crWritten = true;
|
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
2017-06-02 18:25:04 +02:00
|
|
|
|
|
2014-08-21 16:59:40 +02:00
|
|
|
|
//write spanner ending after the last segment, on the last tick
|
2019-07-01 00:29:25 +02:00
|
|
|
|
if (clip || eseg == 0) {
|
2017-06-02 18:25:04 +02:00
|
|
|
|
for (Spanner* s : spanners) {
|
2014-08-21 16:59:40 +02:00
|
|
|
|
if ((s->tick2() == endTick)
|
2017-12-27 16:09:12 +01:00
|
|
|
|
&& !s->isSlur()
|
2014-08-21 16:59:40 +02:00
|
|
|
|
&& (s->track2() == track || (s->track2() == -1 && s->track() == track))
|
2019-07-01 00:29:25 +02:00
|
|
|
|
&& (!clip || s->tick() >= sseg->tick())
|
2014-08-21 16:59:40 +02:00
|
|
|
|
) {
|
2018-05-23 23:27:23 +02:00
|
|
|
|
s->writeSpannerEnd(xml, lastMeasure(), track, endTick);
|
2014-08-21 16:59:40 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-08-20 17:42:11 +02:00
|
|
|
|
}
|
2018-08-15 00:25:30 +02:00
|
|
|
|
|
|
|
|
|
if (voiceTagWritten)
|
|
|
|
|
xml.etag(); // </voice>
|
2014-08-20 17:42:11 +02:00
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
// searchTuplet
|
|
|
|
|
// search complete Dom for tuplet id
|
2013-01-17 14:55:04 +01:00
|
|
|
|
// last resort in case of error
|
2012-05-26 14:26:10 +02:00
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
|
Tuplet* Score::searchTuplet(XmlReader& /*e*/, int /*id*/)
|
2012-05-26 14:26:10 +02:00
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
|
}
|
|
|
|
|
|