Skip to content

Commit 116debc

Browse files
authored
Merge pull request #30630 from cbjeukendrup/port/4.6.3
Port/4.6.3
2 parents be58a62 + 9bf0e06 commit 116debc

14 files changed

Lines changed: 96 additions & 108 deletions

File tree

buildscripts/packaging/Linux+BSD/org.musescore.MuseScore.appdata.xml.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@
116116
</kudos>
117117
<!-- Only <releases> below this point please! -->
118118
<releases>
119+
<release date="2025-10-21" version="4.6.3">
120+
<url>https://musescore.org/en/4.6.3</url>
121+
</release>
119122
<release date="2025-10-10" version="4.6.2">
120123
<url>https://musescore.org/en/4.6.2</url>
121124
</release>

src/engraving/dom/tiejumppointlist.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,13 @@ void TieJumpPoint::undoSetActive(bool v)
6464
score->undo(new ChangeTieJumpPointActive(m_jumpPointList, m_id, v));
6565
}
6666

67-
const String TieJumpPoint::menuTitle() const
67+
TranslatableString TieJumpPoint::menuTitle() const
6868
{
6969
const Measure* measure = m_note->findMeasure();
7070
const int measureNo = measure ? measure->no() + 1 : 0;
7171

7272
//: %1 represents the preceding jump item eg. coda. %2 represents the measure number
73-
return muse::mtrc("engraving", "Tie to %1 (m. %2)").arg(precedingJumpItemName(), String::number(measureNo));
73+
return TranslatableString("engraving", "Tie to %1 (m. %2)").arg(precedingJumpItemName(), String::number(measureNo));
7474
}
7575

7676
String TieJumpPoint::precedingJumpItemName() const

src/engraving/dom/tiejumppointlist.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
*/
2222

2323
#pragma once
24+
2425
#include "global/types/string.h"
26+
#include "global/types/translatablestring.h"
2527

2628
namespace mu::engraving {
2729
class Note;
@@ -48,7 +50,7 @@ class TieJumpPoint
4850
void setJumpPointList(TieJumpPointList* jumpPointList) { m_jumpPointList = jumpPointList; }
4951
TieJumpPointList* jumpPointList() { return m_jumpPointList; }
5052

51-
const muse::String menuTitle() const;
53+
muse::TranslatableString menuTitle() const;
5254

5355
private:
5456
muse::String precedingJumpItemName() const;

src/framework/global/serialization/textstream.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,11 @@ TextStream& TextStream::operator<<(double val)
101101
|| (!defined(__APPLE__) && defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 14000) \
102102
|| (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 11)
103103
std::array<char, 24> buf{};
104-
const auto [last, ec] = std::to_chars(buf.data(), buf.data() + buf.size(), val);
104+
105+
// emulate std::stringstream default behavior
106+
constexpr auto format = std::chars_format::general;
107+
constexpr int precision = 6;
108+
const auto [last, ec] = std::to_chars(buf.data(), buf.data() + buf.size(), val, format, precision);
105109
IF_ASSERT_FAILED(ec == std::errc {}) {
106110
return *this;
107111
}

src/framework/languages/internal/languagesservice.cpp

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
#include "log.h"
4444

45+
using namespace Qt::Literals::StringLiterals;
46+
4547
using namespace muse;
4648
using namespace muse::languages;
4749
using namespace muse::network;
@@ -211,56 +213,49 @@ void LanguagesService::setCurrentLanguage(const QString& languageCode)
211213

212214
QString LanguagesService::effectiveLanguageCode(QString languageCode) const
213215
{
214-
languageCode.replace('-', '_');
215-
// Tries decreasingly specific versions of `code`. For example:
216-
// "nl_NL" -> not found -> try just "nl" -> found -> returns "nl".
217-
auto tryCode = [this](QString code) -> QString {
218-
for (;;) {
219-
if (m_languagesHash.contains(code)) {
220-
return code;
221-
}
216+
languageCode.replace(u'-', u'_');
222217

223-
static const std::map<QString, QString> SPECIAL_CASES {
224-
{ "ca_valencia", "ca@valencia" },
225-
{ "ca_ES_valencia", "ca@valencia" },
226-
{ "en_AU", "en_GB" },
227-
{ "en_NZ", "en_GB" },
228-
{ "en", "en_US" },
229-
{ "hi", "hi_IN" },
230-
{ "mn", "mn_MN" },
231-
{ "zh", "zh_CN" }
232-
};
233-
234-
auto it = SPECIAL_CASES.find(code);
235-
if (it != SPECIAL_CASES.cend()) {
236-
return it->second;
237-
}
238-
239-
int rightmost = code.lastIndexOf('_');
240-
if (rightmost <= 0) {
241-
break;
242-
}
218+
auto tryCode = [this](const QString& code) -> QString {
219+
if (m_languagesHash.contains(code)) {
220+
return code;
221+
}
243222

244-
code.truncate(rightmost);
223+
static const std::map<QString, QString> SPECIAL_CASES {
224+
{ u"ca_valencia"_s, u"ca@valencia"_s },
225+
{ u"ca_ES_valencia"_s, u"ca@valencia"_s },
226+
{ u"en_AU"_s, u"en_GB"_s },
227+
{ u"en_NZ"_s, u"en_GB"_s },
228+
{ u"en"_s, u"en_US"_s },
229+
{ u"hi"_s, u"hi_IN"_s },
230+
{ u"mn"_s, u"mn_MN"_s },
231+
{ u"zh"_s, u"zh_CN"_s }
232+
};
233+
234+
auto it = SPECIAL_CASES.find(code);
235+
if (it != SPECIAL_CASES.cend()) {
236+
return it->second;
245237
}
246238

247239
// Not found
248240
return QString();
249241
};
250242

251243
if (languageCode.isEmpty() || languageCode == SYSTEM_LANGUAGE_CODE) {
252-
for (const QString& code : QLocale::system().uiLanguages()) {
253-
LOGI() << "System language code: " << code;
254-
QString effectiveCode = code;
255-
effectiveCode.replace('-', '_');
244+
const QStringList systemLanguages = QLocale::system().uiLanguages();
245+
LOGI() << "System languages: " << systemLanguages;
246+
247+
for (QString code : systemLanguages) {
248+
code.replace(u'-', u'_');
249+
256250
// Prefer Swedish (Modern) over Swedish (Traditional)
257251
// when using system language.
258-
if (effectiveCode == "sv_SE") {
259-
effectiveCode = "sv";
252+
if (code == u"sv_SE"_s) {
253+
code = u"sv"_s;
260254
}
261-
effectiveCode = tryCode(effectiveCode);
262-
if (!effectiveCode.isEmpty()) {
263-
return effectiveCode;
255+
256+
code = tryCode(code);
257+
if (!code.isEmpty()) {
258+
return code;
264259
}
265260
}
266261

src/importexport/musicxml/internal/musicxml/export/exportmusicxml.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -832,19 +832,22 @@ static String slurTieBezier(const SlurTie* st, const bool start)
832832

833833
String attributeString;
834834
const int spatium = st->spatium();
835-
if (start) {
836-
const SlurTieSegment* front = toSlurTieSegment(st->frontSegment());
837-
const PointF startP = front->ups(Grip::START).pos();
838-
const PointF bezierP = front->ups(Grip::BEZIER1).pos();
839-
attributeString += String(u" bezier-x=\"%1\"").arg(10 * (bezierP.x() - startP.x()) / spatium);
840-
attributeString += String(u" bezier-y=\"%1\"").arg(-10 * (bezierP.y() - startP.y()) / spatium);
841-
} else {
842-
const SlurTieSegment* back = toSlurTieSegment(st->backSegment());
843-
const PointF endP = back->ups(Grip::END).pos();
844-
const PointF bezierP = back->ups(Grip::BEZIER2).pos();
845-
attributeString += String(u" bezier-x=\"%1\"").arg(10 * (bezierP.x() - endP.x()) / spatium);
846-
attributeString += String(u" bezier-y=\"%1\"").arg(-10 * (bezierP.y() - endP.y()) / spatium);
835+
if (!st->spannerSegments().empty()) {
836+
if (start) {
837+
const SlurTieSegment* front = toSlurTieSegment(st->frontSegment());
838+
const PointF startP = front->ups(Grip::START).pos();
839+
const PointF bezierP = front->ups(Grip::BEZIER1).pos();
840+
attributeString += String(u" bezier-x=\"%1\"").arg(10 * (bezierP.x() - startP.x()) / spatium);
841+
attributeString += String(u" bezier-y=\"%1\"").arg(-10 * (bezierP.y() - startP.y()) / spatium);
842+
} else {
843+
const SlurTieSegment* back = toSlurTieSegment(st->backSegment());
844+
const PointF endP = back->ups(Grip::END).pos();
845+
const PointF bezierP = back->ups(Grip::BEZIER2).pos();
846+
attributeString += String(u" bezier-x=\"%1\"").arg(10 * (bezierP.x() - endP.x()) / spatium);
847+
attributeString += String(u" bezier-y=\"%1\"").arg(-10 * (bezierP.y() - endP.y()) / spatium);
848+
}
847849
}
850+
848851
return attributeString;
849852
}
850853

@@ -936,9 +939,11 @@ void SlurHandler::doSlurs(const ChordRest* chordRest, Notations& notations, XmlW
936939
if (sp->generated() || !sp->isSlur()) {
937940
continue;
938941
}
939-
if (sp->isHammerOnPullOff()) {
942+
if (sp->isHammerOnPullOff() && !sp->spannerSegments().empty()) {
940943
const HammerOnPullOffSegment* hopoSeg = static_cast<const HammerOnPullOffSegment*>(sp->spannerSegments().front());
941-
tagName = hopoSeg->hopoText().front()->isHammerOn() ? u"hammer-on" : u"pull-off";
944+
if (!hopoSeg->hopoText().empty()) {
945+
tagName = hopoSeg->hopoText().front()->isHammerOn() ? u"hammer-on" : u"pull-off";
946+
}
942947
}
943948
if (chordRest == sp->startElement() || chordRest == sp->endElement()) {
944949
const Slur* s = static_cast<const Slur*>(sp);

src/importexport/musicxml/internal/musicxml/import/importmusicxmlpass2.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7248,7 +7248,7 @@ Note* MusicXmlParserPass2::note(const String& partId,
72487248
// handle notations
72497249
if (cr) {
72507250
notations.addToScore(cr, note,
7251-
noteStartTime.ticks(), m_slurs, m_glissandi, m_spanners, m_trills, m_ties, m_unstartedTieNotes,
7251+
noteStartTime, m_slurs, m_glissandi, m_spanners, m_trills, m_ties, m_unstartedTieNotes,
72527252
m_unendedTieNotes, arpMap, delayedArps);
72537253

72547254
// if no tie added yet, convert the "tie" into "tied" and add it.
@@ -8187,7 +8187,7 @@ void MusicXmlParserNotations::slur()
81878187
// addSlur
81888188
//---------------------------------------------------------
81898189

8190-
static void addSlur(const Notation& notation, SlurStack& slurs, ChordRest* cr, Note* note, const int tick,
8190+
static void addSlur(const Notation& notation, SlurStack& slurs, ChordRest* cr, Note* note, const Fraction& tick,
81918191
MusicXmlLogger* logger, const XmlStreamReader* const xmlreader)
81928192
{
81938193
int slurNo = notation.attribute(u"number").toInt();
@@ -8212,8 +8212,9 @@ static void addSlur(const Notation& notation, SlurStack& slurs, ChordRest* cr, N
82128212
} else if (slurs[slurNo].isStop()) {
82138213
// slur start when slur already stopped: wrap up
82148214
Slur* newSlur = slurs[slurNo].slur();
8215+
slurs[slurNo] = SlurDesc();
8216+
82158217
if (newSlur->endElement() == cr && note) {
8216-
slurs[slurNo] = SlurDesc();
82178218
delete newSlur;
82188219

82198220
// Slur starts & ends on same chord - add lv instead
@@ -8222,16 +8223,16 @@ static void addSlur(const Notation& notation, SlurStack& slurs, ChordRest* cr, N
82228223
note->score()->undoAddElement(lvTie);
82238224
return;
82248225
}
8225-
newSlur->setTrack(track);
8226-
newSlur->setTick(Fraction::fromTicks(tick));
8227-
newSlur->setStartElement(cr);
8228-
newSlur->setTick2(newSlur->endElement()->tick());
8229-
if (newSlur->ticks().negative()) {
8226+
const Fraction tick2 = newSlur->endElement()->tick();
8227+
if (tick2 < tick) {
82308228
logger->logError(String(u"slur end is before slur start"), xmlreader);
8231-
slurs[slurNo] = SlurDesc();
82328229
delete newSlur;
82338230
return;
82348231
}
8232+
newSlur->setTrack(track);
8233+
newSlur->setTick(tick);
8234+
newSlur->setStartElement(cr);
8235+
newSlur->setTick2(tick2);
82358236
score->addElement(newSlur);
82368237
} else {
82378238
// slur start for new slur: init
@@ -8251,7 +8252,7 @@ static void addSlur(const Notation& notation, SlurStack& slurs, ChordRest* cr, N
82518252
}
82528253
newSlur->setVisible(notation.visible());
82538254
colorItem(newSlur, Color::fromString(notation.attribute(u"color")));
8254-
newSlur->setTick(Fraction::fromTicks(tick));
8255+
newSlur->setTick(tick);
82558256
newSlur->setStartElement(cr);
82568257
if (configuration()->importLayout()) {
82578258
const String orientation = notation.attribute(u"orientation");
@@ -8274,9 +8275,9 @@ static void addSlur(const Notation& notation, SlurStack& slurs, ChordRest* cr, N
82748275
if (slurs[slurNo].isStart()) {
82758276
// slur stop when slur already started: wrap up
82768277
Slur* newSlur = slurs[slurNo].slur();
8278+
slurs[slurNo] = SlurDesc();
82778279

82788280
if (newSlur->startElement() == cr && note) {
8279-
slurs[slurNo] = SlurDesc();
82808281
delete newSlur;
82818282

82828283
// Slur starts & ends on same chord - add lv instead
@@ -8287,11 +8288,10 @@ static void addSlur(const Notation& notation, SlurStack& slurs, ChordRest* cr, N
82878288
}
82888289

82898290
if (!(cr->isGrace())) {
8290-
newSlur->setTick2(Fraction::fromTicks(tick));
8291+
newSlur->setTick2(tick);
82918292
newSlur->setTrack2(track);
82928293
}
82938294
newSlur->setEndElement(cr);
8294-
slurs[slurNo] = SlurDesc();
82958295
score->addElement(newSlur);
82968296
} else if (slurs[slurNo].isStop()) {
82978297
// slur stop when slur already stopped: report error
@@ -9335,14 +9335,14 @@ void MusicXmlParserNotations::addNotation(const Notation& notation, ChordRest* c
93359335
as in that case note is a nullptr.
93369336
*/
93379337

9338-
void MusicXmlParserNotations::addToScore(ChordRest* const cr, Note* const note, const int tick, SlurStack& slurs,
9338+
void MusicXmlParserNotations::addToScore(ChordRest* const cr, Note* const note, const Fraction& tick, SlurStack& slurs,
93399339
Glissando* glissandi[MAX_NUMBER_LEVEL][2], MusicXmlSpannerMap& spanners,
93409340
TrillStack& trills, MusicXmlTieMap& ties, std::vector<Note*>& unstartedTieNotes,
93419341
std::vector<Note*>& unendedTieNotes, ArpeggioMap& arpMap,
93429342
DelayedArpMap& delayedArps)
93439343
{
93449344
addArpeggio(cr, m_arpeggioType, m_arpeggioNo, m_arpeggioColor, arpMap, delayedArps);
9345-
addWavyLine(cr, Fraction::fromTicks(tick), m_wavyLineNo, m_wavyLineType, spanners, trills, m_logger, &m_e);
9345+
addWavyLine(cr, tick, m_wavyLineNo, m_wavyLineType, spanners, trills, m_logger, &m_e);
93469346

93479347
for (const Notation& notation : m_notations) {
93489348
if (notation.symId() != SymId::noSym) {
@@ -9367,7 +9367,7 @@ void MusicXmlParserNotations::addToScore(ChordRest* const cr, Note* const note,
93679367
Dynamic* dynamic = Factory::createDynamic(m_score->dummy()->segment());
93689368
dynamic->setDynamicType(d);
93699369
colorItem(dynamic, m_dynamicsColor);
9370-
m_pass2.addElemOffset(dynamic, cr->track(), m_dynamicsPlacement, cr->measure(), Fraction::fromTicks(tick));
9370+
m_pass2.addElemOffset(dynamic, cr->track(), m_dynamicsPlacement, cr->measure(), tick);
93719371
}
93729372
}
93739373

src/importexport/musicxml/internal/musicxml/import/importmusicxmlpass2.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ class MusicXmlParserNotations
344344
public:
345345
MusicXmlParserNotations(muse::XmlStreamReader& e, engraving::Score* score, MusicXmlLogger* logger, MusicXmlParserPass2& pass2);
346346
void parse();
347-
void addToScore(engraving::ChordRest* const cr, engraving::Note* const note, const int tick, SlurStack& slurs,
347+
void addToScore(engraving::ChordRest* const cr, engraving::Note* const note, const engraving::Fraction& tick, SlurStack& slurs,
348348
engraving::Glissando* glissandi[MAX_NUMBER_LEVEL][2], MusicXmlSpannerMap& spanners, TrillStack& trills,
349349
MusicXmlTieMap& ties, std::vector<engraving::Note*>& unstartedTieNotes, std::vector<engraving::Note*>& unendedTieNotes,
350350
ArpeggioMap& arpMap, DelayedArpMap& delayedArps);

src/inspector/internal/services/elementrepositoryservice.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,10 @@ EngravingItem* ElementRepositoryService::findTextDelegate(EngravingItem* element
397397
switch (element->type()) {
398398
case ElementType::BAR_LINE: {
399399
Segment* seg = toBarLine(element)->segment();
400-
PlayCountText* playCountText = toPlayCountText(seg->findAnnotation(ElementType::PLAY_COUNT_TEXT, 0, 0));
401-
return playCountText;
400+
if (PlayCountText* playCountText = toPlayCountText(seg->findAnnotation(ElementType::PLAY_COUNT_TEXT, 0, 0))) {
401+
return playCountText;
402+
}
403+
return element;
402404
}
403405
default:
404406
return element;

src/notation/internal/notationinteraction.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2743,7 +2743,6 @@ void NotationInteraction::applyPaletteElementToRange(EngravingItem* element, boo
27432743
}
27442744
default: break;
27452745
}
2746-
return;
27472746
}
27482747

27492748
const track_idx_t track1 = sel.staffStart() * mu::engraving::VOICES;

0 commit comments

Comments
 (0)