Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New score and parts interactions #18722

Merged
merged 14 commits into from
Sep 26, 2023
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
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