Skip to content

Commit 200be72

Browse files
Merge pull request #29587 from Eism/fdl_prs_port_4.6
Fdl PRs port 4.6
2 parents e7fb167 + 96c3dea commit 200be72

File tree

21 files changed

+352
-128
lines changed

21 files changed

+352
-128
lines changed

src/engraving/dom/box.cpp

Lines changed: 118 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static const ElementStyle boxStyle {
5454
static const ElementStyle hBoxStyle {
5555
};
5656

57-
static const String FRET_BOX_DIAGRAMS_ORDER_SEPARATOR = u",";
57+
static const String FRET_BOX_DIAGRAMS_SEPARATOR = u",";
5858

5959
Box::Box(const ElementType& type, System* parent)
6060
: MeasureBase(type, parent)
@@ -752,7 +752,7 @@ void FBox::init()
752752
for (size_t i = 0; i < oldDiagramsNames.size(); ++i) {
753753
String oldName = oldDiagramsNames[i];
754754
if (!muse::contains(diagramsNamesInScore, oldName)) {
755-
score()->undoRemoveElement(oldDiagrams[i]);
755+
score()->undo(new RemoveFretDiagramFromFretBox(oldDiagrams[i]));
756756
}
757757
}
758758

@@ -761,62 +761,71 @@ void FBox::init()
761761
if (!muse::contains(oldDiagramsNames, newName)) {
762762
FretDiagram* newDiagram = FretDiagram::makeFromHarmonyOrFretDiagram(harmonyOrDiagramsInScore[i]);
763763
newDiagram->setParent(this);
764-
score()->undoAddElement(newDiagram);
764+
String nameOfDiagramBeforeThis = i > 0 ? diagramsNamesInScore[i - 1] : String();
765+
size_t idx = computeInsertionIdx(nameOfDiagramBeforeThis);
766+
score()->undo(new AddFretDiagramToFretBox(newDiagram, idx));
765767
}
766768
}
767769

768-
if (m_diagramsOrder.empty()) {
769-
return;
770-
}
771-
772-
std::vector<String /*harmonyName*/> currentDiagramsOrder;
770+
StringList currentDiagrams;
773771
for (EngravingItem* item : el()) {
774-
currentDiagramsOrder.push_back(toFretDiagram(item)->harmony()->harmonyName().toLower());
772+
currentDiagrams.push_back(toFretDiagram(item)->harmonyText().toLower());
775773
}
776774

777-
if (currentDiagramsOrder != m_diagramsOrder) {
778-
m_diagramsOrder.erase(std::remove_if(m_diagramsOrder.begin(), m_diagramsOrder.end(),
779-
[&](const String& harmonyName) { return !muse::contains(currentDiagramsOrder, harmonyName); }),
780-
m_diagramsOrder.end());
781-
782-
String previousHarmonyName;
783-
for (const String& harmonyName : currentDiagramsOrder) {
784-
if (!muse::contains(m_diagramsOrder, harmonyName)) {
785-
size_t index = 0;
786-
if (!previousHarmonyName.empty()) {
787-
index = std::find(m_diagramsOrder.begin(), m_diagramsOrder.end(), previousHarmonyName) - m_diagramsOrder.begin() + 1;
788-
}
789-
790-
m_diagramsOrder.insert(m_diagramsOrder.begin() + index, harmonyName);
791-
}
775+
if (!m_invisibleDiagrams.empty()) {
776+
updateInvisibleDiagrams(currentDiagrams);
777+
}
792778

793-
previousHarmonyName = harmonyName;
794-
}
779+
if (!m_diagramsOrder.empty()) {
780+
updateDiagramsOrder(currentDiagrams);
795781
}
796782
}
797783

798784
void FBox::add(EngravingItem* e)
799785
{
800786
e->setParent(this);
801787
if (e->isFretDiagram()) {
802-
FretDiagram* fretDiagram = toFretDiagram(e);
803-
fretDiagram->setFlag(ElementFlag::MOVABLE, false);
804-
fretDiagram->setFlag(ElementFlag::ON_STAFF, false);
788+
addAtIdx(toFretDiagram(e), muse::nidx);
789+
} else {
790+
LOGD("FBox::add: element not allowed");
791+
return;
792+
}
793+
}
805794

806-
Harmony* harmony = fretDiagram->harmony();
807-
harmony->setFlag(ElementFlag::MOVABLE, false);
808-
harmony->setFlag(ElementFlag::ON_STAFF, false);
795+
void FBox::addAtIdx(FretDiagram* fretDiagram, size_t idx)
796+
{
797+
fretDiagram->setTrack(muse::nidx);
798+
fretDiagram->setFlag(ElementFlag::MOVABLE, false);
799+
fretDiagram->setFlag(ElementFlag::ON_STAFF, false);
809800

810-
if (!e->eid().isValid()) {
811-
e->assignNewEID();
812-
}
801+
Harmony* harmony = fretDiagram->harmony();
802+
harmony->setTrack(muse::nidx);
803+
harmony->setFlag(ElementFlag::MOVABLE, false);
804+
harmony->setFlag(ElementFlag::ON_STAFF, false);
813805

814-
VBox::add(e);
806+
if (idx < m_el.size()) {
807+
m_el.insert(m_el.begin() + idx, fretDiagram);
815808
} else {
816-
LOGD("FBox::add: element not allowed");
817-
return;
809+
m_el.push_back(fretDiagram);
810+
}
811+
812+
fretDiagram->added();
813+
}
814+
815+
size_t FBox::computeInsertionIdx(const String& nameOfDiagramBeforeThis)
816+
{
817+
if (nameOfDiagramBeforeThis.empty()) {
818+
return 0;
818819
}
819-
e->added();
820+
821+
for (size_t i = 0; i < m_el.size(); ++i) {
822+
FretDiagram* fretDiagram = toFretDiagram(m_el[i]);
823+
if (fretDiagram->harmonyText().toLower() == nameOfDiagramBeforeThis.toLower()) {
824+
return i + 1;
825+
}
826+
}
827+
828+
return muse::nidx;
820829
}
821830

822831
PropertyValue FBox::getProperty(Pid propertyId) const
@@ -839,7 +848,9 @@ PropertyValue FBox::getProperty(Pid propertyId) const
839848
case Pid::RIGHT_MARGIN:
840849
return m_contentAlignmentH == AlignH::RIGHT ? VBox::getProperty(propertyId) : PropertyValue();
841850
case Pid::FRET_FRAME_DIAGRAMS_ORDER:
842-
return !m_diagramsOrder.empty() ? m_diagramsOrder.join(FRET_BOX_DIAGRAMS_ORDER_SEPARATOR) : PropertyValue();
851+
return !m_diagramsOrder.empty() ? m_diagramsOrder.join(FRET_BOX_DIAGRAMS_SEPARATOR) : PropertyValue();
852+
case Pid::FRET_FRAME_INVISIBLE_DIAGRAMS:
853+
return !m_invisibleDiagrams.empty() ? m_invisibleDiagrams.join(FRET_BOX_DIAGRAMS_SEPARATOR) : PropertyValue();
843854
default:
844855
return VBox::getProperty(propertyId);
845856
}
@@ -869,7 +880,10 @@ bool FBox::setProperty(Pid propertyId, const PropertyValue& val)
869880
resetProperty(Pid::RIGHT_MARGIN);
870881
break;
871882
case Pid::FRET_FRAME_DIAGRAMS_ORDER:
872-
m_diagramsOrder = val.value<String>().split(FRET_BOX_DIAGRAMS_ORDER_SEPARATOR); // todo
883+
m_diagramsOrder = val.value<String>().split(FRET_BOX_DIAGRAMS_SEPARATOR);
884+
break;
885+
case Pid::FRET_FRAME_INVISIBLE_DIAGRAMS:
886+
m_invisibleDiagrams = val.value<String>().split(FRET_BOX_DIAGRAMS_SEPARATOR);
873887
break;
874888
default:
875889
return VBox::setProperty(propertyId, val);
@@ -894,6 +908,8 @@ PropertyValue FBox::propertyDefault(Pid propertyId) const
894908
return static_cast<int>(AlignH::HCENTER);
895909
case Pid::FRET_FRAME_DIAGRAMS_ORDER:
896910
return PropertyValue();
911+
case Pid::FRET_FRAME_INVISIBLE_DIAGRAMS:
912+
return PropertyValue();
897913
default:
898914
return VBox::propertyDefault(propertyId);
899915
}
@@ -926,31 +942,87 @@ void FBox::undoReorderElements(const StringList& newOrder)
926942
order.push_back(harmonyName.toLower());
927943
}
928944

929-
undoChangeProperty(Pid::FRET_FRAME_DIAGRAMS_ORDER, order.join(FRET_BOX_DIAGRAMS_ORDER_SEPARATOR));
945+
undoChangeProperty(Pid::FRET_FRAME_DIAGRAMS_ORDER, order.join(FRET_BOX_DIAGRAMS_SEPARATOR));
930946
triggerLayout();
931947
}
932948

933-
ElementList FBox::orderedElements() const
949+
ElementList FBox::orderedElements(bool includeInvisible) const
934950
{
935951
ElementList elements = el();
936-
std::vector<String> diagramsOrder = this->diagramsOrder();
952+
const StringList& diagramsOrder = this->diagramsOrder();
953+
if (diagramsOrder.empty()) {
954+
return elements;
955+
}
937956

938957
std::sort(elements.begin(), elements.end(), [&diagramsOrder](const EngravingItem* a, const EngravingItem* b) {
939958
const FretDiagram* diagramA = toFretDiagram(a);
940-
const String diagramAHarmonyName = diagramA->harmony()->harmonyName().toLower();
959+
const String diagramAHarmonyName = diagramA->harmonyText().toLower();
941960

942961
const FretDiagram* diagramB = toFretDiagram(b);
943-
const String diagramBHarmonyName = diagramB->harmony()->harmonyName().toLower();
962+
const String diagramBHarmonyName = diagramB->harmonyText().toLower();
944963

945964
auto itA = std::find(diagramsOrder.begin(), diagramsOrder.end(), diagramAHarmonyName);
946965
auto itB = std::find(diagramsOrder.begin(), diagramsOrder.end(), diagramBHarmonyName);
947966

948967
return itA < itB;
949968
});
950969

970+
if (!includeInvisible) {
971+
const StringList& invisibleDiagrams = this->invisibleDiagrams();
972+
973+
muse::remove_if(elements, [&invisibleDiagrams](const EngravingItem* element){
974+
const FretDiagram* diagram = toFretDiagram(element);
975+
const String diagramHarmonyName = diagram->harmonyText().toLower();
976+
return muse::contains(invisibleDiagrams, diagramHarmonyName);
977+
});
978+
}
979+
951980
return elements;
952981
}
953982

983+
void FBox::undoSetInvisibleDiagrams(const StringList& invisibleDiagrams)
984+
{
985+
StringList diagrams;
986+
for (const String& harmonyName : invisibleDiagrams) {
987+
diagrams.push_back(harmonyName.toLower());
988+
}
989+
990+
undoChangeProperty(Pid::FRET_FRAME_INVISIBLE_DIAGRAMS, diagrams.join(FRET_BOX_DIAGRAMS_SEPARATOR));
991+
triggerLayout();
992+
}
993+
994+
void FBox::updateDiagramsOrder(const StringList& currentDiagrams)
995+
{
996+
if (currentDiagrams == m_diagramsOrder) {
997+
return;
998+
}
999+
1000+
m_diagramsOrder.erase(std::remove_if(m_diagramsOrder.begin(), m_diagramsOrder.end(),
1001+
[&](const String& harmonyName) { return !muse::contains(currentDiagrams, harmonyName); }),
1002+
m_diagramsOrder.end());
1003+
1004+
String previousHarmonyName;
1005+
for (const String& harmonyName : currentDiagrams) {
1006+
if (!muse::contains(m_diagramsOrder, harmonyName)) {
1007+
size_t index = 0;
1008+
if (!previousHarmonyName.empty()) {
1009+
index = std::find(m_diagramsOrder.begin(), m_diagramsOrder.end(), previousHarmonyName) - m_diagramsOrder.begin() + 1;
1010+
}
1011+
1012+
m_diagramsOrder.insert(m_diagramsOrder.begin() + index, harmonyName);
1013+
}
1014+
1015+
previousHarmonyName = harmonyName;
1016+
}
1017+
}
1018+
1019+
void FBox::updateInvisibleDiagrams(const StringList& currentDiagrams)
1020+
{
1021+
m_invisibleDiagrams.erase(std::remove_if(m_invisibleDiagrams.begin(), m_invisibleDiagrams.end(),
1022+
[&](const String& harmonyName) { return !muse::contains(currentDiagrams, harmonyName); }),
1023+
m_invisibleDiagrams.end());
1024+
}
1025+
9541026
//---------------------------------------------------------
9551027
// TBox
9561028
//---------------------------------------------------------

src/engraving/dom/box.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ class FBox : public VBox
189189
void init();
190190

191191
void add(EngravingItem*) override;
192+
void addAtIdx(FretDiagram* fretDiagram, size_t idx);
192193

193194
double textScale() const { return m_textScale; }
194195
double diagramScale() const { return m_diagramScale; }
@@ -207,14 +208,22 @@ class FBox : public VBox
207208
std::vector<PointF> gripsPositions(const EditData&) const override;
208209

209210
void undoReorderElements(const StringList& newOrder);
210-
StringList diagramsOrder() const { return m_diagramsOrder; }
211+
const StringList& diagramsOrder() const { return m_diagramsOrder; }
211212

212-
ElementList orderedElements() const;
213+
void undoSetInvisibleDiagrams(const StringList& invisibleDiagrams);
214+
const StringList& invisibleDiagrams() const { return m_invisibleDiagrams; }
215+
216+
ElementList orderedElements(bool includeInvisible = false) const;
213217

214218
bool needsRebuild() const { return m_needsRebuild; }
215219
void setNeedsRebuild(bool v) { m_needsRebuild = v; }
216220

217221
private:
222+
223+
void updateDiagramsOrder(const StringList& currentDiagrams);
224+
void updateInvisibleDiagrams(const StringList& currentDiagrams);
225+
size_t computeInsertionIdx(const String& nameOfDiagramBeforeThis);
226+
218227
double m_textScale = 0.0;
219228
double m_diagramScale = 0.0;
220229
Spatium m_columnGap;
@@ -226,6 +235,7 @@ class FBox : public VBox
226235
AlignH m_contentAlignmentH = AlignH::HCENTER;
227236

228237
StringList /*harmonyNames*/ m_diagramsOrder;
238+
StringList /*harmonyNames*/ m_invisibleDiagrams;
229239
};
230240

231241
//---------------------------------------------------------

src/engraving/dom/edit.cpp

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3886,6 +3886,37 @@ void Score::cmdDeleteSelection()
38863886
// so we don't try to delete them twice if they are also in selection
38873887
std::set<Spanner*> deletedSpanners;
38883888

3889+
// diagrams in the fret box must be processed first than diagrams outside the box,
3890+
// which causes the fret box to be rebuilt and all elements inside to be deleted
3891+
std::sort(el.begin(), el.end(), [&](const EngravingItem* item1, const EngravingItem* item2) {
3892+
bool inBox1 = isElementInFretBox(item1);
3893+
bool inBox2 = isElementInFretBox(item2);
3894+
3895+
return inBox1 == inBox2 ? false : inBox1;
3896+
});
3897+
3898+
// if there is harmony or fret diagram outside the fret box
3899+
// then the fret box will be rebuilt and we should exclude fret box's elements
3900+
bool hasHarmonyOrFretDiagramsInFretBox = false;
3901+
bool hasHarmonyOrFretDiagramsOutFretBox = false;
3902+
for (const EngravingItem* element : el) {
3903+
if (!element->isFretDiagram() && !element->isHarmony()) {
3904+
continue;
3905+
}
3906+
3907+
if (isElementInFretBox(element)) {
3908+
hasHarmonyOrFretDiagramsInFretBox = true;
3909+
} else {
3910+
hasHarmonyOrFretDiagramsOutFretBox = true;
3911+
}
3912+
3913+
if (hasHarmonyOrFretDiagramsInFretBox && hasHarmonyOrFretDiagramsOutFretBox) {
3914+
break;
3915+
}
3916+
}
3917+
3918+
bool willFretBoxBeRebuilded = hasHarmonyOrFretDiagramsInFretBox && hasHarmonyOrFretDiagramsOutFretBox;
3919+
38893920
auto selectCRAtTickAndTrack = [this, &crsSelectedAfterDeletion](Fraction tick, track_idx_t track) {
38903921
ChordRest* cr = findCR(tick, track);
38913922
if (cr) {
@@ -3959,16 +3990,42 @@ void Score::cmdDeleteSelection()
39593990

39603991
// We can't delete elements inside fret box, instead we hide them
39613992
if (e->isFretDiagram() || e->isHarmony()) {
3993+
auto excludeElementFromSelectionInfo = [this](EngravingItem* element) {
3994+
// we need to exclude elements ftom undo stack selection info,
3995+
// so that when trying to return the selection there is no crash
3996+
UndoMacro* activeCommand = undoStack()->activeCommand();
3997+
activeCommand->excludeElementFromSelectionInfo(element);
3998+
};
3999+
4000+
if (willFretBoxBeRebuilded && isElementInFretBox(e)) {
4001+
excludeElementFromSelectionInfo(e);
4002+
continue;
4003+
}
4004+
4005+
auto hideDiagramInFretBox = [&excludeElementFromSelectionInfo](FBox* fbox, EngravingItem* element){
4006+
StringList invisibleDiagrams = fbox->invisibleDiagrams();
4007+
const String harmonyName = element->isFretDiagram() ? toFretDiagram(element)->harmony()->harmonyName().toLower()
4008+
: toHarmony(element)->harmonyName().toLower();
4009+
4010+
invisibleDiagrams.push_back(harmonyName);
4011+
fbox->undoSetInvisibleDiagrams(invisibleDiagrams);
4012+
4013+
excludeElementFromSelectionInfo(element);
4014+
};
4015+
39624016
if (e->isFretDiagram() && toFretDiagram(e)->isInFretBox()) {
3963-
undoChangeVisible(e, false);
3964-
elSelectedAfterDeletion = toFBox(e->explicitParent());
4017+
FBox* fbox = toFBox(e->explicitParent());
4018+
hideDiagramInFretBox(fbox, toFretDiagram(e));
4019+
elSelectedAfterDeletion = fbox;
39654020
continue;
39664021
} else if (e->isHarmony()) {
39674022
EngravingObject* parent = toHarmony(e)->explicitParent();
39684023
FretDiagram* fretDiagram = parent->isFretDiagram() ? toFretDiagram(parent) : nullptr;
4024+
39694025
if (fretDiagram && fretDiagram->isInFretBox()) {
3970-
undoChangeVisible(fretDiagram, false);
3971-
elSelectedAfterDeletion = toFBox(fretDiagram->explicitParent());
4026+
FBox* fbox = toFBox(fretDiagram->explicitParent());
4027+
hideDiagramInFretBox(fbox, fretDiagram);
4028+
elSelectedAfterDeletion = fbox;
39724029
continue;
39734030
}
39744031
}

src/engraving/dom/fret.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,10 +1346,6 @@ FretDiagram* FretDiagram::makeFromHarmonyOrFretDiagram(const EngravingItem* harm
13461346
}
13471347
}
13481348

1349-
if (fretDiagram) {
1350-
fretDiagram->setTrack(muse::nidx);
1351-
}
1352-
13531349
return fretDiagram;
13541350
}
13551351

0 commit comments

Comments
 (0)