Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/translate_lupdate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ on:
schedule:
- cron: "0 12 * * Sun"

env:
USE_QT69: ${{ inputs.use_qt69 != '' && inputs.use_qt69 || 'on' }}

jobs:
lupdate:
runs-on: ubuntu-latest
Expand All @@ -35,11 +38,10 @@ jobs:
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: ${{ inputs.use_qt69 == 'on' && '6.9.1' || '6.2.4' }}
version: ${{ env.USE_QT69 == 'on' && '6.9.1' || '6.2.4' }}
host: "linux"
target: "desktop"
arch: ${{ inputs.use_qt69 == 'on' && 'linux_gcc_64' || 'gcc_64' }}
archives: "qttools qtbase icu"
arch: ${{ env.USE_QT69== 'on' && 'linux_gcc_64' || 'gcc_64' }}

- name: Run lupdate
run: |
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/translate_tx_pull_to_s3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ jobs:
host: "linux"
target: "desktop"
arch: ${{ env.USE_QT69== 'on' && 'linux_gcc_64' || 'gcc_64' }}
archives: "qttools qtbase icu"

- name: Setup environment for pushing to S3
if: env.DO_PUSH_TO_S3 == 'true'
Expand Down
3 changes: 3 additions & 0 deletions src/engraving/dom/ambitus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,9 @@ EngravingItem* Ambitus::prevSegmentElement()

String Ambitus::accessibleInfo() const
{
if (m_topTpc == Tpc::TPC_INVALID || m_bottomTpc == Tpc::TPC_INVALID) {
return EngravingItem::accessibleInfo();
}
return EngravingItem::accessibleInfo() + u"; "
+ muse::mtrc("engraving", "Top pitch: %1; Bottom pitch: %2")
.arg(tpc2name(topTpc(), NoteSpellingType::STANDARD, NoteCaseType::AUTO, false) + String::number(topOctave()),
Expand Down
4 changes: 2 additions & 2 deletions src/engraving/dom/anchors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,15 @@ void EditTimeTickAnchors::updateAnchors(const EngravingItem* item)
item->triggerLayout();
}

void EditTimeTickAnchors::updateAnchors(Measure* measure, staff_idx_t staffIdx)
void EditTimeTickAnchors::updateAnchors(Measure* measure, staff_idx_t staffIdx, const std::set<Fraction>& additionalAnchorRelTicks)
{
Fraction startTick = Fraction(0, 1);
Fraction endTick = measure->ticks();

Fraction timeSig = measure->timesig();
Fraction halfDivision = Fraction(1, 2 * timeSig.denominator());

std::set<Fraction> anchorTicks;
std::set<Fraction> anchorTicks { additionalAnchorRelTicks };
for (Fraction tick = startTick; tick <= endTick; tick += halfDivision) {
anchorTicks.insert(tick);
}
Expand Down
8 changes: 3 additions & 5 deletions src/engraving/dom/anchors.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef MU_ENGRAVING_ANCHORS_H
#define MU_ENGRAVING_ANCHORS_H
#pragma once

#include "engravingitem.h"
#include "score.h"
Expand All @@ -33,7 +32,7 @@ class EditTimeTickAnchors
{
public:
static void updateAnchors(const EngravingItem* item);
static void updateAnchors(Measure* measure, staff_idx_t staffIdx);
static void updateAnchors(Measure* measure, staff_idx_t staffIdx, const std::set<Fraction>& additionalAnchorRelTicks = {});
static TimeTickAnchor* createTimeTickAnchor(Measure* measure, Fraction relTick, staff_idx_t staffIdx);
static void updateLayout(Measure* measure);
};
Expand Down Expand Up @@ -90,5 +89,4 @@ class TimeTickAnchor : public EngravingItem
};
DECLARE_LAYOUTDATA_METHODS(TimeTickAnchor)
};
} // namespace mu::engraving
#endif // MU_ENGRAVING_ANCHORS_H
}
35 changes: 4 additions & 31 deletions src/engraving/dom/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -727,42 +727,15 @@ Measure* Score::pos2measure(const PointF& p, staff_idx_t* rst, int* pitch, Segme
/// \b output: new segment for drag position
//---------------------------------------------------------

void Score::dragPosition(const PointF& p, staff_idx_t* rst, Segment** seg, double spacingFactor, bool allowTimeAnchor) const
void Score::dragPosition(const PointF& pos, staff_idx_t* rst, Segment** seg, double spacingFactor, bool allowTimeAnchor) const
{
const System* preferredSystem = (*seg) ? (*seg)->system() : nullptr;
Measure* m = searchMeasure(p, preferredSystem, spacingFactor);
if (m == 0 || m->isMMRest()) {
return;
}

System* s = m->system();
double y = p.y() - s->canvasPos().y();

const staff_idx_t i = s->searchStaff(y, *rst, spacingFactor);

// search for segment + offset
PointF pppp = p - m->canvasPos();
track_idx_t strack = staff2track(i);
if (!staff(i)) {
return;
}
track_idx_t etrack = staff2track(i + 1);
Measure* m = nullptr;

SegmentType st = allowTimeAnchor ? Segment::CHORD_REST_OR_TIME_TICK_TYPE : SegmentType::ChordRest;
Segment* segment = m->searchSegment(pppp.x(), st, strack, etrack, *seg, spacingFactor);
if (segment) {
if (segment->isTimeTickType()) {
if (Segment* crAtSamePos = m->findSegmentR(SegmentType::ChordRest, segment->rtick())) {
// If TimeTick and ChordRest at same position, prefer ChordRest
segment = crAtSamePos;
}
}
*rst = i;
*seg = segment;
if (!dragPositionToMeasure(pos, this, &m, rst, spacingFactor)) {
return;
}

return;
dragPositionToSegment(pos, m, *rst, seg, spacingFactor, allowTimeAnchor);
}

//---------------------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions src/engraving/dom/textbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,11 @@ void TextBlock::changeFormat(FormatId id, const FormatValue& data, int start, in
for (auto i = m_fragments.begin(); i != m_fragments.end(); ++i) {
int columns = i->columns();
if (start + n <= col) {
if (columns == 0) {
// still apply the format change. Otherwise we have deviating formats for e. g. empty lines
// otherwise we have Issue #19571
i->changeFormat(id, data);
}
break;
}
if (start >= col + columns) {
Expand Down
57 changes: 57 additions & 0 deletions src/engraving/dom/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,63 @@ Fraction actualTicks(Fraction duration, Tuplet* tuplet, Fraction timeStretch)
return f;
}

bool dragPositionToMeasure(const PointF& pos, const Score* score,
Measure** measure, staff_idx_t* staffIdx,
const double spacingFactor)
{
const System* preferredSystem = (*measure) ? (*measure)->system() : nullptr;

Measure* m = score->searchMeasure(pos, preferredSystem, spacingFactor);
if (!m) {
return false;
}

const System* system = m->system();
const double y = pos.y() - system->canvasPos().y();
const staff_idx_t i = system->searchStaff(y, *staffIdx, spacingFactor);
if (!score->staff(i)) {
return false;
}

*measure = m;
*staffIdx = i;
return true;
}

bool dragPositionToSegment(const PointF& pos, const Measure* measure, const staff_idx_t staffIdx,
Segment** segment,
const double spacingFactor, const bool allowTimeAnchor)
{
const track_idx_t strack = staffIdx * VOICES;
const track_idx_t etrack = strack + VOICES;

const double x = pos.x() - measure->canvasPos().x();
const SegmentType st = allowTimeAnchor ? Segment::CHORD_REST_OR_TIME_TICK_TYPE : SegmentType::ChordRest;
Segment* s = measure->searchSegment(x, st, strack, etrack, *segment, spacingFactor);
if (!s) {
return false;
}

*segment = segmentOrChordRestSegmentAtSameTick(s);
return true;
}

Segment* segmentOrChordRestSegmentAtSameTick(Segment* segment)
{
IF_ASSERT_FAILED(segment) {
return nullptr;
}

// If TimeTick and ChordRest segments are at the same tick, prefer ChordRest
if (segment->isTimeTickType() && segment->measure()) {
if (Segment* crSegAtSameTick = segment->measure()->findSegmentR(SegmentType::ChordRest, segment->rtick())) {
return crSegAtSameTick;
}
}

return segment;
}

double yStaffDifference(const System* system1, const System* system2, staff_idx_t staffIdx)
{
if (!system1 || !system2) {
Expand Down
6 changes: 6 additions & 0 deletions src/engraving/dom/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ extern Segment* skipTuplet(Tuplet* tuplet);
extern SymIdList timeSigSymIdsFromString(const String&, TimeSigStyle timeSigStyle = TimeSigStyle::NORMAL);
extern Fraction actualTicks(Fraction duration, Tuplet* tuplet, Fraction timeStretch);

extern bool dragPositionToMeasure(const PointF& pos, const Score* score, Measure** measure, staff_idx_t* staffIdx,
const double spacingFactor = 0.5);
extern bool dragPositionToSegment(const PointF& pos, const Measure* measure, const staff_idx_t staffIdx, Segment** segment,
const double spacingFactor = 0.5, const bool allowTimeAnchor = false);
extern Segment* segmentOrChordRestSegmentAtSameTick(Segment* segment);

extern double yStaffDifference(const System* system1, const System* system2, staff_idx_t staffIdx1);

extern bool allowRemoveWhenRemovingStaves(EngravingItem* item, staff_idx_t startStaff, staff_idx_t endStaff = 0);
Expand Down
29 changes: 22 additions & 7 deletions src/engraving/internal/engravingfont.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,15 @@ void EngravingFont::ensureLoad()
}

std::string error;
JsonObject metadataJson = JsonDocument::fromJson(metadataFile.readAll(), &error).rootObject();
const JsonObject metadataJson = JsonDocument::fromJson(metadataFile.readAll(), &error).rootObject();
if (!error.empty()) {
LOGE() << "Json parse error in " << metadataFile.filePath() << ", error: " << error;
return;
}
if (!metadataJson.isValid()) {
LOGE() << "No valid JSON object in " << metadataFile.filePath();
return;
}

loadGlyphsWithAnchors(metadataJson.value("glyphsWithAnchors").toObject());
loadComposedGlyphs();
Expand All @@ -142,16 +146,23 @@ void EngravingFont::ensureLoad()

void EngravingFont::loadGlyphsWithAnchors(const JsonObject& glyphsWithAnchors)
{
if (!glyphsWithAnchors.isValid()) {
return;
}

for (const std::string& symName : glyphsWithAnchors.keys()) {
SymId symId = SymNames::symIdByName(symName);
const SymId symId = SymNames::symIdByName(symName);
if (symId == SymId::noSym) {
//! NOTE currently, Bravura contains a bunch of entries in glyphsWithAnchors
//! for glyph names that will not be found - flag32ndUpStraight, etc.
continue;
}

Sym& sym = this->sym(symId);
JsonObject anchors = glyphsWithAnchors.value(symName).toObject();
const JsonObject anchors = glyphsWithAnchors.value(symName).toObject();
if (!anchors.isValid()) {
continue;
}

static const std::unordered_map<std::string, SmuflAnchorId> smuflAnchorIdNames {
{ "stemDownNW", SmuflAnchorId::stemDownNW },
Expand All @@ -166,15 +177,15 @@ void EngravingFont::loadGlyphsWithAnchors(const JsonObject& glyphsWithAnchors)
};

for (const std::string& anchorId : anchors.keys()) {
auto search = smuflAnchorIdNames.find(anchorId);
const auto search = smuflAnchorIdNames.find(anchorId);
if (search == smuflAnchorIdNames.cend()) {
//LOGD() << "Unhandled SMuFL anchorId: " << anchorId;
continue;
}

JsonArray arr = anchors.value(anchorId).toArray();
double x = arr.at(0).toDouble();
double y = arr.at(1).toDouble();
const JsonArray arr = anchors.value(anchorId).toArray();
const double x = arr.at(0).toDouble();
const double y = arr.at(1).toDouble();

sym.smuflAnchors[search->second] = PointF(x, -y) * SPATIUM20;
}
Expand Down Expand Up @@ -715,6 +726,10 @@ void EngravingFont::loadStylisticAlternates(const JsonObject& glyphsWithAlternat

void EngravingFont::loadEngravingDefaults(const JsonObject& engravingDefaultsObject)
{
if (!engravingDefaultsObject.isValid()) {
return;
}

struct EngravingDefault {
std::vector<Sid> sids;

Expand Down
29 changes: 29 additions & 0 deletions src/engraving/tests/textbase_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,35 @@ TEST_F(Engraving_TextBaseTests, undoChangeFontStyleProperty)
EXPECT_EQ(staffText->xmlText(), u"normal bold underline italic");
}

TEST_F(Engraving_TextBaseTests, undoChangeFontSizeEmptyLines) // Testcase for Issue #19571
{
MasterScore* score = ScoreRW::readScore(u"test.mscx");
StaffText* staffText = addStaffText(score);

String originalText = u"<font size=\"25\"/>Line 1\nLine 2\n\n\nLine 5"; // Two lines of text, two empty lines, one line of text.
String expectedText = u"<font size=\"30\"/>Line 1\nLine 2\n\n\nLine 5"; // The font size should change for all lines, including the empty ones.

staffText->setXmlText(originalText);
LOGD("Text is initially: %s", muPrintable(staffText->xmlText().replace(u"\n", u"\\n")));
score->renderer()->layoutItem(staffText);

score->startCmd(TranslatableString::untranslatable("Engraving text base tests"));
staffText->undoChangeProperty(Pid::FONT_SIZE, PropertyValue::fromValue(30.0), PropertyFlags::UNSTYLED); // Change font size from 25 to 30
score->endCmd();

LOGD(" 1.: Text is now : %s", muPrintable(staffText->xmlText().replace(u"\n", u"\\n")));
EXPECT_EQ(staffText->xmlText(), expectedText); // The font size should change for all lines, including the empty ones.

EditData ed;
score->undoStack()->undo(&ed);
LOGD(" 2.: Text is now : %s", muPrintable(staffText->xmlText().replace(u"\n", u"\\n")));
EXPECT_EQ(staffText->xmlText(), originalText);

score->undoStack()->redo(&ed);
LOGD(" 3.: Text is now : %s", muPrintable(staffText->xmlText().replace(u"\n", u"\\n")));
EXPECT_EQ(staffText->xmlText(), expectedText);
}

TEST_F(Engraving_TextBaseTests, musicalSymbolsNotBold)
{
MasterScore* score = ScoreRW::readScore(u"test.mscx");
Expand Down
14 changes: 6 additions & 8 deletions src/engraving/types/typesconv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,16 +617,14 @@ static const std::array ELEMENT_TYPES {
TranslatableString("engraving", "tapping", nullptr, 1),
TranslatableString("engraving", "Tapping", nullptr, 1) },
Item{ ElementType::TAPPING_HALF_SLUR, "TappingHalfSlur",
TranslatableString("engraving", "tapping half slur", nullptr, 1),
TranslatableString("engraving", "Tapping half slur", nullptr, 1),
},
TranslatableString("engraving", "tapping half slur(s)", nullptr, 1),
TranslatableString("engraving", "Tapping half slur(s)", nullptr, 1) },
Item{ ElementType::TAPPING_HALF_SLUR_SEGMENT, "TappingHalfSlurSegment",
TranslatableString("engraving", "tapping half slur segment"),
TranslatableString("engraving", "Tapping half slur segment") },
TranslatableString("engraving", "tapping half slur segment(s)", nullptr, 1),
TranslatableString("engraving", "Tapping half slur segment(s)", nullptr, 1) },
Item{ ElementType::TAPPING_TEXT, "TappingText",
TranslatableString("engraving", "tapping text"),
TranslatableString("engraving", "Tapping text"),
},
TranslatableString("engraving", "tapping text(s)", nullptr, 1),
TranslatableString("engraving", "Tapping text(s)", nullptr, 1) },
Item{ ElementType::ROOT_ITEM, "RootItem",
TranslatableString::untranslatable("root item"),
TranslatableString::untranslatable("Root item") },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Item {
navigation.column: root.navigationColumnOrderStart
navigation.accessible.name: root.pathFieldTitle + " " + pathField.currentText

onTextChanged: function(newTextValue) {
onTextEditingFinished: function(newTextValue) {
root.pathEdited(newTextValue)
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/inspector/view/qml/MuseScore/Inspector/InspectorForm.qml
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,6 @@ Rectangle {

spacing: 12

cacheBuffer: Math.max(0, contentHeight)

function ensureContentVisible(invisibleContentHeight) {
if (sectionList.contentY + invisibleContentHeight > 0) {
sectionList.contentY += invisibleContentHeight
Expand All @@ -107,6 +105,10 @@ Rectangle {

onContentHeightChanged: {
returnToBounds()

if (contentHeight > cacheBuffer) {
cacheBuffer = contentHeight
}
}

delegate: Column {
Expand Down
Loading
Loading