Skip to content

Commit

Permalink
Merge pull request #18722 from mike-spa/partScorePropertyLinking
Browse files Browse the repository at this point in the history
New score and parts interactions
  • Loading branch information
mike-spa authored Sep 26, 2023
2 parents 35db753 + 64cbb5b commit 62fe329
Show file tree
Hide file tree
Showing 721 changed files with 3,380 additions and 3,149 deletions.
24 changes: 24 additions & 0 deletions src/engraving/dom/box.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "actionicon.h"
#include "factory.h"
#include "layoutbreak.h"
#include "masterscore.h"
#include "mscore.h"
#include "score.h"
#include "stafftext.h"
Expand All @@ -51,6 +52,7 @@ static const ElementStyle hBoxStyle {
Box::Box(const ElementType& type, System* parent)
: MeasureBase(type, parent)
{
setExcludeFromOtherParts(propertyDefault(Pid::EXCLUDE_FROM_OTHER_PARTS).toBool());
}

//---------------------------------------------------------
Expand Down Expand Up @@ -255,6 +257,8 @@ PropertyValue Box::propertyDefault(Pid id) const
return 0.0;
case Pid::BOX_AUTOSIZE:
return true;
case Pid::EXCLUDE_FROM_OTHER_PARTS:
return true;
default:
return MeasureBase::propertyDefault(id);
}
Expand Down Expand Up @@ -416,6 +420,26 @@ EngravingItem* Box::drop(EditData& data)
return 0;
}

void Box::manageExclusionFromParts(bool exclude)
{
if (exclude) {
EngravingItem::manageExclusionFromParts(exclude);
} else {
std::vector<MeasureBase*> newFrames;
for (Score* score : masterScore()->scoreList()) {
if (score == this->score()) {
continue;
}
MeasureBase* newFrame = score->insertMeasure(type(), next());
newFrame->setExcludeFromOtherParts(false);
newFrames.push_back(newFrame);
}
for (MeasureBase* newFrame : newFrames) {
newFrame->linkTo(this);
}
}
}

//---------------------------------------------------------
// drag
//---------------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions src/engraving/dom/box.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ class Box : public MeasureBase
Grip defaultGrip() const override { return Grip::START; }
std::vector<mu::PointF> gripsPositions(const EditData&) const override { return { mu::PointF() }; } // overridden in descendants

bool canBeExcludedFromOtherParts() const override { return true; }
void manageExclusionFromParts(bool exclude) override;

private:
Spatium m_boxWidth; // only valid for HBox
Spatium m_boxHeight; // only valid for VBox
Expand Down
14 changes: 14 additions & 0 deletions src/engraving/dom/clef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,20 @@ void Clef::undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps)
}
}

void Clef::manageExclusionFromParts(bool exclude)
{
if (exclude) {
EngravingItem::manageExclusionFromParts(exclude);
} else {
Measure* measure = findMeasure();
EngravingItem* nextEl = measure && rtick() == measure->ticks() ? measure->next() : nullptr;
if (!nextEl) {
nextEl = nextElement();
}
score()->undoChangeClef(staff(), nextEl, clefType(), false, this);
}
}

//---------------------------------------------------------
// propertyDefault
//---------------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions src/engraving/dom/clef.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ class Clef final : public EngravingItem
bool isHeader() const { return m_isHeader; }
void setIsHeader(bool val) { m_isHeader = val; }

bool canBeExcludedFromOtherParts() const override { return true; }
void manageExclusionFromParts(bool exclude) override;

struct LayoutData : public EngravingItem::LayoutData {
SymId symId = SymId::noSym;
};
Expand Down
119 changes: 81 additions & 38 deletions src/engraving/dom/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3992,16 +3992,20 @@ MeasureBase* Score::insertMeasure(ElementType type, MeasureBase* beforeMeasure,
tick = last() ? last()->endTick() : Fraction(0, 1);
}

Fraction currentTimeSig = sigmap()->timesig(tick.ticks()).nominal(); // use nominal time signature of current measure
const Fraction currentTimeSig = sigmap()->timesig(tick.ticks()).nominal(); // use nominal time signature of current measure
Measure* localMeasure = nullptr; // measure base in "this" score
MeasureBase* linkedMasterMeasure = nullptr; // measure base in root score (for linking)
Fraction ticks = { 0, 1 };

MeasureBase* result = nullptr;
bool isBeginning = tick.isZero();
const bool isBeginning = tick.isZero();

const bool isFrame = type == ElementType::FBOX || type == ElementType::HBOX || type == ElementType::TBOX || type == ElementType::VBOX;
const bool isTitleFrame = (type == ElementType::VBOX || type == ElementType::TBOX) && isBeginning;
const bool dontCloneFrameToParts = isFrame && !isTitleFrame;

std::list<Score*> scores;
if (options.addToAllScores) {
if (options.addToAllScores && !dontCloneFrameToParts) {
scores = scoreList();
} else {
scores.push_back(this);
Expand Down Expand Up @@ -4031,6 +4035,7 @@ MeasureBase* Score::insertMeasure(ElementType type, MeasureBase* beforeMeasure,

MeasureBase* newMeasureBase = toMeasureBase(Factory::createItem(type, score->dummy()));
newMeasureBase->setTick(tick);
newMeasureBase->setExcludeFromOtherParts(dontCloneFrameToParts);

if (score == this) {
result = newMeasureBase;
Expand Down Expand Up @@ -4918,34 +4923,41 @@ void Score::cloneVoice(track_idx_t strack, track_idx_t dtrack, Segment* sf, cons
// return true if an property was actually changed
//---------------------------------------------------------

bool Score::undoPropertyChanged(EngravingItem* e, Pid t, const PropertyValue& st, PropertyFlags ps)
bool Score::undoPropertyChanged(EngravingItem* item, Pid propId, const PropertyValue& propValue, PropertyFlags propFlags)
{
bool changed = false;

if (propertyLink(t) && e->links()) {
for (EngravingObject* ee : *e->links()) {
if (ee == e) {
if (ee->getProperty(t) != st) {
undoStack()->push1(new ChangeProperty(ee, t, st, ps));
changed = true;
}
} else {
// property in linked element has not changed yet
// push() calls redo() to change it
if (ee->getProperty(t) != e->getProperty(t)) {
undoStack()->push(new ChangeProperty(ee, t, e->getProperty(t), ps), 0);
changed = true;
}
}
const PropertyValue currentPropValue = item->getProperty(propId);
const PropertyFlags currentPropFlags = item->propertyFlags(propId);

if ((currentPropValue != propValue) || (currentPropFlags != propFlags)) {
item->setPropertyFlags(propId, propFlags);
undoStack()->push1(new ChangeProperty(item, propId, propValue, propFlags));
changed = true;
}

const std::list<EngravingObject*> linkedItems = item->linkListForPropertyPropagation();

for (EngravingObject* linkedItem : linkedItems) {
if (linkedItem == item) {
continue;
}
} else {
PropertyFlags po = e->propertyFlags(t);
if ((e->getProperty(t) != st) || (ps != po)) {
e->setPropertyFlags(t, ps);
undoStack()->push1(new ChangeProperty(e, t, st, po));
changed = true;
PropertyPropagation propertyPropagate = item->propertyPropagation(toEngravingItem(linkedItem), propId);
switch (propertyPropagate) {
case PropertyPropagation::PROPAGATE:
if (linkedItem->getProperty(propId) != currentPropValue) {
undoStack()->push(new ChangeProperty(linkedItem, propId, currentPropValue, propFlags), nullptr);
changed = true;
}
break;
case PropertyPropagation::UNLINK:
item->unlinkPropertyFromMaster(propId);
break;
default:
break;
}
}

return changed;
}

Expand Down Expand Up @@ -5132,7 +5144,7 @@ void Score::updateInstrumentChangeTranspositions(KeySigEvent& key, Staff* staff,
// create a clef before element e
//---------------------------------------------------------

void Score::undoChangeClef(Staff* ostaff, EngravingItem* e, ClefType ct, bool forInstrumentChange)
void Score::undoChangeClef(Staff* ostaff, EngravingItem* e, ClefType ct, bool forInstrumentChange, Clef* clefToRelink)
{
IF_ASSERT_FAILED(ostaff && e) {
return;
Expand Down Expand Up @@ -5170,8 +5182,9 @@ void Score::undoChangeClef(Staff* ostaff, EngravingItem* e, ClefType ct, bool fo
Fraction rtick = e->rtick();
bool isSmall = (st == SegmentType::Clef);
for (Staff* staff : ostaff->staffList()) {
// if (staff->staffType(tick)->group() != ClefInfo::staffGroup(ct))
// continue;
if (clefToRelink && ostaff == staff) {
continue;
}

Score* score = staff->score();
Measure* measure = score->tick2measure(tick);
Expand Down Expand Up @@ -5252,6 +5265,16 @@ void Score::undoChangeClef(Staff* ostaff, EngravingItem* e, ClefType ct, bool fo
clef->setForInstrumentChange(true);
}
clef->setSmall(isSmall);

if (clefToRelink) {
LinkedObjects* links = clef->links();
if (!links) {
clef->linkTo(clefToRelink);
} else if (!clef->isLinked(clefToRelink)) {
clefToRelink->setLinks(links);
links->push_back(clefToRelink);
}
}
}
}

Expand Down Expand Up @@ -5730,7 +5753,7 @@ void Score::undoChangeVisible(EngravingItem* item, bool visible)
// undoAddElement
//---------------------------------------------------------

void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool ctrlModifier)
void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool ctrlModifier, EngravingItem* elementToRelink)
{
Staff* ostaff = element->staff();
track_idx_t strack = mu::nidx;
Expand Down Expand Up @@ -5783,6 +5806,10 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
}
}

if (elementToRelink) {
staffList.remove(ostaff);
}

bool originalAdded = false;
for (Staff* staff : staffList) {
if (!staff) {
Expand Down Expand Up @@ -5959,6 +5986,10 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
staves.push_back(ostaff);
}

if (elementToRelink) {
staves.remove(ostaff);
}

for (Staff* staff : staves) {
Score* score = staff->score();
staff_idx_t staffIdx = staff->idx();
Expand Down Expand Up @@ -6330,6 +6361,16 @@ void Score::undoAddElement(EngravingItem* element, bool addToLinkedStaves, bool
LOGW("undoAddElement: unhandled: <%s>", element->typeName());
}
ne->styleChanged();

if (elementToRelink) {
LinkedObjects* links = ne->links();
if (!links) {
ne->linkTo(elementToRelink);
} else {
elementToRelink->setLinks(links);
links->push_back(elementToRelink);
}
}
}
}
}
Expand Down Expand Up @@ -6468,24 +6509,26 @@ void Score::undoAddCR(ChordRest* cr, Measure* measure, const Fraction& tick)
// undoRemoveElement
//---------------------------------------------------------

void Score::undoRemoveElement(EngravingItem* element)
void Score::undoRemoveElement(EngravingItem* element, bool removeLinked)
{
if (!element) {
return;
}
std::list<Segment*> segments;
for (EngravingObject* ee : element->linkList()) {
EngravingItem* e = static_cast<EngravingItem*>(ee);
undo(new RemoveElement(e));
if (e == element || removeLinked) {
undo(new RemoveElement(e));

if (e->explicitParent() && (e->explicitParent()->isSegment())) {
Segment* s = toSegment(e->explicitParent());
if (!mu::contains(segments, s)) {
segments.push_back(s);
if (e->explicitParent() && (e->explicitParent()->isSegment())) {
Segment* s = toSegment(e->explicitParent());
if (!mu::contains(segments, s)) {
segments.push_back(s);
}
}
if (e->explicitParent() && e->explicitParent()->isSystem()) {
e->setParent(0); // systems will be regenerated upon redo, so detach
}
}
if (e->explicitParent() && e->explicitParent()->isSystem()) {
e->setParent(0); // systems will be regenerated upon redo, so detach
}
}

Expand Down
Loading

0 comments on commit 62fe329

Please sign in to comment.