Skip to content

Commit

Permalink
Merge pull request #26648 from RomanPudashkin/undo_add_instrument_crash
Browse files Browse the repository at this point in the history
Fix #26598: Crash after adding instrument, Undo and Redo
  • Loading branch information
RomanPudashkin authored Feb 21, 2025
2 parents 230a276 + a6ec17b commit 416deee
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 49 deletions.
17 changes: 17 additions & 0 deletions src/engraving/dom/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,23 @@ struct ScoreChangesRange {
{
return isValidBoundary() || !changedTypes.empty();
}

void clear()
{
*this = ScoreChangesRange();
}

void combine(const ScoreChangesRange& r)
{
tickFrom = std::min(tickFrom, r.tickFrom);
tickTo = std::max(tickTo, r.tickTo);
staffIdxFrom = std::min(staffIdxFrom, r.staffIdxFrom);
staffIdxTo = std::max(staffIdxTo, r.staffIdxTo);
changedItems.insert(r.changedItems.begin(), r.changedItems.end());
changedTypes.insert(r.changedTypes.begin(), r.changedTypes.end());
changedPropertyIdSet.insert(r.changedPropertyIdSet.begin(), r.changedPropertyIdSet.end());
changedStyleIdSet.insert(r.changedStyleIdSet.begin(), r.changedStyleIdSet.end());
}
};
} // namespace mu::engraving

Expand Down
4 changes: 4 additions & 0 deletions src/instrumentsscene/view/abstractlayoutpaneltreeitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ void AbstractLayoutPanelTreeItem::removeChildren(int row, int count, bool delete
}
}

void AbstractLayoutPanelTreeItem::onScoreChanged(const mu::engraving::ScoreChangesRange&)
{
}

AbstractLayoutPanelTreeItem* AbstractLayoutPanelTreeItem::parentItem() const
{
return m_parent;
Expand Down
2 changes: 2 additions & 0 deletions src/instrumentsscene/view/abstractlayoutpaneltreeitem.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class AbstractLayoutPanelTreeItem : public QObject

virtual void removeChildren(int row, int count = 1, bool deleteChild = false);

virtual void onScoreChanged(const mu::engraving::ScoreChangesRange& changes);

AbstractLayoutPanelTreeItem* parentItem() const;
void setParentItem(AbstractLayoutPanelTreeItem* parent);

Expand Down
42 changes: 32 additions & 10 deletions src/instrumentsscene/view/layoutpaneltreemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,11 +269,20 @@ void LayoutPanelTreeModel::setupStavesConnections(const muse::ID& stavesPartId)
});
}

void LayoutPanelTreeModel::listenNotationSelectionChanged()
void LayoutPanelTreeModel::setupNotationConnections()
{
m_notation->interaction()->selectionChanged().onNotify(this, [this]() {
updateSelectedRows();
});

m_notation->undoStack()->changesChannel().onReceive(this, [this](const mu::engraving::ScoreChangesRange& changes) {
if (!m_layoutPanelVisible) {
m_scoreChangesCache.combine(changes);
return;
}

onScoreChanged(changes);
});
}

void LayoutPanelTreeModel::updateSelectedRows()
Expand Down Expand Up @@ -307,6 +316,17 @@ void LayoutPanelTreeModel::updateSelectedRows()
}
}

void LayoutPanelTreeModel::onScoreChanged(const mu::engraving::ScoreChangesRange& changes)
{
if (!m_rootItem) {
return;
}

for (AbstractLayoutPanelTreeItem* item : m_rootItem->childItems()) {
item->onScoreChanged(changes);
}
}

void LayoutPanelTreeModel::clear()
{
TRACEFUNC;
Expand Down Expand Up @@ -362,7 +382,7 @@ void LayoutPanelTreeModel::load()
endResetModel();

setupPartsConnections();
listenNotationSelectionChanged();
setupNotationConnections();

emit isEmptyChanged();
emit isAddingAvailableChanged(true);
Expand Down Expand Up @@ -405,6 +425,11 @@ void LayoutPanelTreeModel::setLayoutPanelVisible(bool visible)

if (visible) {
updateSelectedRows();

if (m_scoreChangesCache.isValid()) {
onScoreChanged(m_scoreChangesCache);
m_scoreChangesCache.clear();
}
}
}

Expand Down Expand Up @@ -964,7 +989,8 @@ void LayoutPanelTreeModel::updateSystemObjectLayers()
m_shouldUpdateSystemObjectLayers = false;

// Create copy, because we're going to modify them
std::vector<Staff*> newSystemObjectStaves = m_masterNotation->notation()->parts()->systemObjectStaves();
const INotationPartsPtr notationParts = m_masterNotation->notation()->parts();
std::vector<Staff*> newSystemObjectStaves = notationParts->systemObjectStaves();
QList<AbstractLayoutPanelTreeItem*> children = m_rootItem->childItems();

// Remove old system object layers
Expand All @@ -991,6 +1017,8 @@ void LayoutPanelTreeModel::updateSystemObjectLayers()
endRemoveRows();
}

SystemObjectGroupsByStaff systemObjects = collectSystemObjectGroups(notationParts->systemObjectStaves());

// Update position of existing layers if changed
for (SystemObjectsLayerTreeItem* layerItem : existingSystemObjectLayers) {
const PartTreeItem* partItem = findPartItemByStaff(layerItem->staff());
Expand All @@ -1007,16 +1035,10 @@ void LayoutPanelTreeModel::updateSystemObjectLayers()
endMoveRows();
}

layerItem->updateSystemObjects();
}

if (newSystemObjectStaves.empty()) {
return;
layerItem->setSystemObjects(systemObjects[layerItem->staff()]);
}

// Create new system object layers
SystemObjectGroupsByStaff systemObjects = collectSystemObjectGroups(newSystemObjectStaves);

for (const Staff* staff : newSystemObjectStaves) {
for (const PartTreeItem* partItem : partItems) {
if (staff->part() != partItem->part()) {
Expand Down
7 changes: 5 additions & 2 deletions src/instrumentsscene/view/layoutpaneltreemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,10 @@ private slots:

void setupPartsConnections();
void setupStavesConnections(const muse::ID& stavesPartId);
void listenNotationSelectionChanged();
void setupNotationConnections();

void updateSelectedRows();
void onScoreChanged(const mu::engraving::ScoreChangesRange& changes);

void clear();
void deleteItems();
Expand Down Expand Up @@ -183,8 +185,9 @@ private slots:
using NotationKey = QString;
QHash<NotationKey, QList<muse::ID> > m_sortedPartIdList;

bool m_layoutPanelVisible = true;
mu::engraving::ScoreChangesRange m_scoreChangesCache;

bool m_layoutPanelVisible = true;
bool m_shouldUpdateSystemObjectLayers = false;

bool m_dragInProgress = false;
Expand Down
15 changes: 4 additions & 11 deletions src/instrumentsscene/view/systemobjectslayertreeitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,13 @@ SystemObjectsLayerTreeItem::SystemObjectsLayerTreeItem(IMasterNotationPtr master

void SystemObjectsLayerTreeItem::init(const Staff* staff, const SystemObjectGroups& systemObjects)
{
m_systemObjectGroups = systemObjects;

setStaff(staff);
setSystemObjects(systemObjects);

bool isTopLayer = staff->score()->staff(0) == staff;
setIsRemovable(!isTopLayer);
setIsSelectable(!isTopLayer);

updateState();

notation()->undoStack()->changesChannel().onReceive(this, [this](const ChangesRange& changes) {
onUndoStackChanged(changes);
});

connect(this, &AbstractLayoutPanelTreeItem::isVisibleChanged, this, [this](bool isVisible) {
onVisibleChanged(isVisible);
});
Expand All @@ -127,9 +120,9 @@ void SystemObjectsLayerTreeItem::setStaff(const Staff* staff)
}
}

void SystemObjectsLayerTreeItem::updateSystemObjects()
void SystemObjectsLayerTreeItem::setSystemObjects(const SystemObjectGroups& systemObjects)
{
m_systemObjectGroups = collectSystemObjectGroups(m_staff);
m_systemObjectGroups = systemObjects;
updateState();
}

Expand All @@ -144,7 +137,7 @@ bool SystemObjectsLayerTreeItem::canAcceptDrop(const QVariant&) const
return false;
}

void SystemObjectsLayerTreeItem::onUndoStackChanged(const mu::engraving::ScoreChangesRange& changes)
void SystemObjectsLayerTreeItem::onScoreChanged(const mu::engraving::ScoreChangesRange& changes)
{
if (muse::contains(changes.changedPropertyIdSet, Pid::TRACK)) {
updateStaff();
Expand Down
7 changes: 3 additions & 4 deletions src/instrumentsscene/view/systemobjectslayertreeitem.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@
#pragma once

#include "abstractlayoutpaneltreeitem.h"
#include "async/asyncable.h"

#include "notation/inotationparts.h"

#include "layoutpanelutils.h"

namespace mu::instrumentsscene {
class SystemObjectsLayerTreeItem : public AbstractLayoutPanelTreeItem, public muse::async::Asyncable
class SystemObjectsLayerTreeItem : public AbstractLayoutPanelTreeItem
{
Q_OBJECT

Expand All @@ -41,13 +40,13 @@ class SystemObjectsLayerTreeItem : public AbstractLayoutPanelTreeItem, public mu

const mu::engraving::Staff* staff() const;
void setStaff(const mu::engraving::Staff* staff);
void updateSystemObjects();
void setSystemObjects(const SystemObjectGroups& systemObjects);

Q_INVOKABLE QString staffId() const;
Q_INVOKABLE bool canAcceptDrop(const QVariant& item) const override;

private:
void onUndoStackChanged(const mu::engraving::ScoreChangesRange& changes);
void onScoreChanged(const mu::engraving::ScoreChangesRange& changes) override;
void onVisibleChanged(bool isVisible);

bool addSystemObject(mu::engraving::EngravingItem* obj);
Expand Down
3 changes: 1 addition & 2 deletions src/notation/internal/masternotationparts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ void MasterNotationParts::setParts(const PartInstrumentList& partList, const Sco
impl->setBracketsAndBarlines();
}

updatePartList();
updateSystemObjectStaves();
updatePartsAndSystemObjectStaves();
endGlobalEdit();
}

Expand Down
31 changes: 14 additions & 17 deletions src/notation/internal/notationparts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ void NotationParts::setParts(const PartInstrumentList& parts, const ScoreOrder&
updateSoloist(parts);
sortParts(parts);
setBracketsAndBarlines();
updatePartList();
updateSystemObjectStaves();
updatePartsAndSystemObjectStaves();

apply();
}
Expand Down Expand Up @@ -330,8 +329,7 @@ void NotationParts::listenUndoStackChanges()
return;
}

updatePartList();
updateSystemObjectStaves();
updatePartsAndSystemObjectStaves();

m_undoStack->changesChannel().onReceive(this, [this](const ChangesRange& range) {
if (range.changedTypes.empty()) {
Expand All @@ -346,23 +344,14 @@ void NotationParts::listenUndoStackChanges()

for (ElementType type : TYPES_TO_CHECK) {
if (muse::contains(range.changedTypes, type)) {
updatePartList();
updateSystemObjectStaves();
updatePartsAndSystemObjectStaves();
return;
}
}
});
}

void NotationParts::updatePartList()
{
if (m_parts != score()->parts()) {
m_parts = score()->parts();
m_partChangedNotifier.changed();
}
}

void NotationParts::updateSystemObjectStaves()
void NotationParts::updatePartsAndSystemObjectStaves()
{
const auto systemObjectStavesWithTopStaff = [this]() {
std::vector<Staff*> result;
Expand All @@ -375,10 +364,18 @@ void NotationParts::updateSystemObjectStaves()
return result;
};

const bool partsChanged = m_parts != score()->parts();
m_parts = score()->parts();

std::vector<Staff*> newSystemObjectStaves = systemObjectStavesWithTopStaff();
const bool systemObjectStavesChanged = m_systemObjectStaves != newSystemObjectStaves;
m_systemObjectStaves = std::move(newSystemObjectStaves);

if (partsChanged) {
m_partChangedNotifier.changed();
}

if (m_systemObjectStaves != newSystemObjectStaves) {
m_systemObjectStaves = std::move(newSystemObjectStaves);
if (systemObjectStavesChanged) {
m_systemObjectStavesChanged.notify();
}
}
Expand Down
4 changes: 1 addition & 3 deletions src/notation/internal/notationparts.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,7 @@ class NotationParts : public INotationParts, public muse::async::Asyncable
friend class MasterNotationParts;

void listenUndoStackChanges();

void updatePartList();
void updateSystemObjectStaves();
void updatePartsAndSystemObjectStaves();

void doSetScoreOrder(const ScoreOrder& order);
void doRemoveParts(const std::vector<Part*>& parts);
Expand Down

0 comments on commit 416deee

Please sign in to comment.