Skip to content

Commit

Permalink
Introduce additional text linking toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-spa authored and cbjeukendrup committed Sep 19, 2023
1 parent 9789266 commit fc9b1e6
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 6 deletions.
20 changes: 18 additions & 2 deletions src/engraving/dom/engravingitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,9 @@ mu::draw::Color EngravingItem::curColor(bool isVisible, Color normalColor) const
if (selected() || marked) {
bool isUnlinkedFromMaster = !(getProperty(Pid::POSITION_LINKED_TO_MASTER).toBool()
&& getProperty(Pid::APPEARANCE_LINKED_TO_MASTER).toBool());
if (isTextBase()) {
isUnlinkedFromMaster = isUnlinkedFromMaster || !getProperty(Pid::TEXT_LINKED_TO_MASTER).toBool();
}
return engravingConfiguration()->selectionColor(track() == mu::nidx ? 0 : voice(), isVisible, isUnlinkedFromMaster);
}

Expand Down Expand Up @@ -1267,7 +1270,9 @@ void EngravingItem::relinkPropertiesToMaster(PropertyGroup propertyGroup)
return;
}

const std::set<Pid>& propertiesToRelink = propertyGroup == PropertyGroup::POSITION ? positionProperties() : appearanceProperties();
const std::set<Pid>& propertiesToRelink = propertyGroup == PropertyGroup::POSITION ? positionProperties()
: propertyGroup == PropertyGroup::APPEARANCE ? appearanceProperties()
: textProperties();

for (Pid propertyId : propertiesToRelink) {
PropertyValue masterValue = masterElement->getProperty(propertyId);
Expand All @@ -1290,6 +1295,7 @@ PropertyPropagation EngravingItem::propertyPropagation(EngravingItem* destinatio
static std::set<Pid> NEVER_PROPAGATING_PROPERTIES = {
Pid::POSITION_LINKED_TO_MASTER,
Pid::APPEARANCE_LINKED_TO_MASTER,
Pid::TEXT_LINKED_TO_MASTER,
Pid::GENERATED,
Pid::EXCLUDE_FROM_OTHER_PARTS
};
Expand All @@ -1300,6 +1306,12 @@ PropertyPropagation EngravingItem::propertyPropagation(EngravingItem* destinatio

Score* sourceScore = score();
Score* destinationScore = destinationItem->score();
bool isTextProperty = mu::contains(textProperties(), propertyId);

if (isTextProperty && isPropertyLinkedToMaster(propertyId) || sourceScore == destinationScore) {
return PropertyPropagation::PROPAGATE;
}

if (sourceScore != destinationScore && !sourceScore->isMaster()) {
// Properties are only propagated when being edited from master. If this is being edited
// from a part score, we mark it as unlinked so it becomes independent in the part.
Expand Down Expand Up @@ -2310,7 +2322,11 @@ bool EngravingItem::isPropertyLinkedToMaster(Pid id) const
return isPositionLinkedToMaster();
}

return isAppearanceLinkedToMaster();
if (mu::contains(appearanceProperties(), id)) {
return isAppearanceLinkedToMaster();
}

return true;
}

void EngravingItem::unlinkPropertyFromMaster(Pid id)
Expand Down
19 changes: 16 additions & 3 deletions src/engraving/dom/property.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,10 @@ static constexpr PropertyMetaData propertyList[] = {
{ Pid::CAPO_IGNORED_STRINGS, true, "ignoredStrings", P_TYPE::INT_VEC, DUMMY_QT_TR_NOOP("propertyName", "ignored strings") },
{ Pid::CAPO_GENERATE_TEXT, true, "generateText", P_TYPE::BOOL, DUMMY_QT_TR_NOOP("propertyName", "automatically generate text") },

{ Pid::POSITION_LINKED_TO_MASTER, false, "positionLinkedToMaster", P_TYPE::BOOL, DUMMY_QT_TR_NOOP("propertyName", "position linked to master") },
{ Pid::APPEARANCE_LINKED_TO_MASTER, false, "appearanceLinkedToMaster", P_TYPE::BOOL, DUMMY_QT_TR_NOOP("propertyName", "position linked to master") },
{ Pid::EXCLUDE_FROM_OTHER_PARTS, false, "excludeFromParts", P_TYPE::BOOL, DUMMY_QT_TR_NOOP("propertyName", "exclude from parts") },
{ Pid::POSITION_LINKED_TO_MASTER, false, "positionLinkedToMaster", P_TYPE::BOOL, DUMMY_QT_TR_NOOP("propertyName", "position linked to master") },
{ Pid::APPEARANCE_LINKED_TO_MASTER, false, "appearanceLinkedToMaster", P_TYPE::BOOL, DUMMY_QT_TR_NOOP("propertyName", "appearance linked to master") },
{ Pid::TEXT_LINKED_TO_MASTER, false, "textLinkedToMaster", P_TYPE::BOOL, DUMMY_QT_TR_NOOP("propertyName", "text linked to master") },
{ Pid::EXCLUDE_FROM_OTHER_PARTS, false, "excludeFromParts", P_TYPE::BOOL, DUMMY_QT_TR_NOOP("propertyName", "exclude from parts") },

{ Pid::END, false, "++end++", P_TYPE::INT, DUMMY_QT_TR_NOOP("propertyName", "<invalid property>") }
};
Expand Down Expand Up @@ -602,13 +603,24 @@ const std::set<Pid>& positionProperties()
return _positionProperties;
}

static const std::set<Pid> _textProperties = {
Pid::TEXT,
Pid::FONT_STYLE,
};

const std::set<Pid>& textProperties()
{
return _textProperties;
}

static std::set<Pid> _appearanceProperties;

const std::set<Pid>& appearanceProperties()
{
static std::set<Pid> excludedProperties {
Pid::POSITION_LINKED_TO_MASTER,
Pid::APPEARANCE_LINKED_TO_MASTER,
Pid::TEXT_LINKED_TO_MASTER,
Pid::EXCLUDE_FROM_OTHER_PARTS,
Pid::PITCH,
Pid::TICK,
Expand All @@ -621,6 +633,7 @@ const std::set<Pid>& appearanceProperties()
for (int i = 0; i < static_cast<int>(Pid::END); ++i) {
Pid propertyId = static_cast<Pid>(i);
bool isAppearanceProperty = !mu::contains(_positionProperties, propertyId)
&& !mu::contains(_textProperties, propertyId)
&& !mu::contains(excludedProperties, propertyId);
if (isAppearanceProperty) {
_appearanceProperties.insert(propertyId);
Expand Down
5 changes: 4 additions & 1 deletion src/engraving/dom/property.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ enum class Pid {

POSITION_LINKED_TO_MASTER,
APPEARANCE_LINKED_TO_MASTER,
TEXT_LINKED_TO_MASTER,
EXCLUDE_FROM_OTHER_PARTS,

END
Expand All @@ -431,6 +432,7 @@ enum class PropertyPropagation {
enum class PropertyGroup {
POSITION,
APPEARANCE,
TEXT,
};

using PropertyIdSet = std::unordered_set<Pid>;
Expand All @@ -444,7 +446,8 @@ extern Pid propertyId(const AsciiStringView& name);
extern String propertyUserName(Pid);

extern const std::set<Pid>& positionProperties(); ///< All the properties that have to do with the position of an item
extern const std::set<Pid>& appearanceProperties(); ///< All the properties that are not position properties
extern const std::set<Pid>& textProperties(); ///< Text body of text items
extern const std::set<Pid>& appearanceProperties(); ///< All the properties that are not position or text properties
} // namespace mu::engraving

#endif
22 changes: 22 additions & 0 deletions src/engraving/dom/textbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2650,6 +2650,15 @@ mu::draw::FontMetrics TextBase::fontMetrics() const
return mu::draw::FontMetrics(font());
}

bool TextBase::isPropertyLinkedToMaster(Pid id) const
{
if (mu::contains(textProperties(), id)) {
return isTextLinkedToMaster();
}

return EngravingItem::isPropertyLinkedToMaster(id);
}

//---------------------------------------------------------
// getProperty
//---------------------------------------------------------
Expand Down Expand Up @@ -2685,6 +2694,8 @@ PropertyValue TextBase::getProperty(Pid propertyId) const
return static_cast<int>(m_cursor->selectedFragmentsFormat().valign());
case Pid::TEXT:
return xmlText();
case Pid::TEXT_LINKED_TO_MASTER:
return isTextLinkedToMaster();
default:
return EngravingItem::getProperty(propertyId);
}
Expand Down Expand Up @@ -2744,6 +2755,15 @@ bool TextBase::setProperty(Pid pid, const PropertyValue& v)
case Pid::TEXT_SCRIPT_ALIGN:
m_cursor->setFormat(FormatId::Valign, v.toInt());
break;
case Pid::TEXT_LINKED_TO_MASTER:
if (isTextLinkedToMaster() == v.toBool()) {
break;
}
if (!isTextLinkedToMaster()) {
relinkPropertiesToMaster(PropertyGroup::TEXT);
}
setTextLinkedToMaster(v.toBool());
break;
default:
rv = EngravingItem::setProperty(pid, v);
break;
Expand Down Expand Up @@ -2783,6 +2803,8 @@ PropertyValue TextBase::propertyDefault(Pid id) const
return String();
case Pid::TEXT_SCRIPT_ALIGN:
return static_cast<int>(VerticalAlignment::AlignNormal);
case Pid::TEXT_LINKED_TO_MASTER:
return true;
default:
for (const auto& p : *textStyle(TextStyleType::DEFAULT)) {
if (p.pid == id) {
Expand Down
3 changes: 3 additions & 0 deletions src/engraving/dom/textbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ class TextBase : public EngravingItem

INJECT(IEngravingFontsProvider, engravingFonts)

M_PROPERTY2(bool, isTextLinkedToMaster, setTextLinkedToMaster, true)

public:

~TextBase();
Expand Down Expand Up @@ -374,6 +376,7 @@ class TextBase : public EngravingItem
mu::draw::Font font() const;
mu::draw::FontMetrics fontMetrics() const;

bool isPropertyLinkedToMaster(Pid id) const override;
PropertyValue getProperty(Pid propertyId) const override;
bool setProperty(Pid propertyId, const PropertyValue& v) override;
PropertyValue propertyDefault(Pid id) const override;
Expand Down
1 change: 1 addition & 0 deletions src/engraving/rw/read410/tread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4181,6 +4181,7 @@ bool TRead::readProperties(TextBase* t, XmlReader& e, ReadContext& ctx)
if (t->isStyled(Pid::FONT_STYLE)) {
t->setPropertyFlags(Pid::FONT_STYLE, PropertyFlags::UNSTYLED);
}
} else if (TRead::readProperty(t, tag, e, ctx, Pid::TEXT_LINKED_TO_MASTER)) {
} else if (!readItemProperties(t, e, ctx)) {
return false;
}
Expand Down
2 changes: 2 additions & 0 deletions src/engraving/rw/write/twrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,8 @@ void TWrite::writeProperties(const TextBase* item, XmlWriter& xml, WriteContext&
if (writeText) {
xml.writeXml(u"text", item->xmlText());
}

writeProperty(item, xml, Pid::TEXT_LINKED_TO_MASTER);
}

void TWrite::write(const Fermata* item, XmlWriter& xml, WriteContext& ctx)
Expand Down
31 changes: 31 additions & 0 deletions src/inspector/models/parts/partssettingsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ void PartsSettingsModel::createProperties()
m_appearanceLinkedToMaster = buildPropertyItem(Pid::APPEARANCE_LINKED_TO_MASTER, [this](const Pid, const QVariant& newValue) {
setPropertyValue(m_elementsForPartLinkingOption, Pid::APPEARANCE_LINKED_TO_MASTER, newValue.toBool());
});
m_textLinkedToMaster = buildPropertyItem(Pid::TEXT_LINKED_TO_MASTER, [this](const Pid, const QVariant& newValue) {
setPropertyValue(m_elementsForTextLinkingOption, Pid::TEXT_LINKED_TO_MASTER, newValue.toBool());
});
m_excludeFromOtherParts = buildPropertyItem(Pid::EXCLUDE_FROM_OTHER_PARTS, [this](const Pid, const QVariant& newValue) {
setPropertyValue(m_elementsForExcludeOption, Pid::EXCLUDE_FROM_OTHER_PARTS, newValue.toBool());
});

updateShowPartLinkingOption();
updateShowExcludeOption();
updateShowTextLinkingOption();
}

void PartsSettingsModel::requestElements()
Expand All @@ -58,6 +62,7 @@ void PartsSettingsModel::requestElements()

m_elementsForPartLinkingOption.clear();
m_elementsForExcludeOption.clear();
m_elementsForTextLinkingOption.clear();

for (EngravingItem* item : m_elementList) {
if (!item->score()->isMaster()) {
Expand All @@ -66,23 +71,29 @@ void PartsSettingsModel::requestElements()
if (item->canBeExcludedFromOtherParts()) {
m_elementsForExcludeOption.push_back(item);
}
if (item->isTextBase()) {
m_elementsForTextLinkingOption.push_back(item);
}
}
}

void PartsSettingsModel::loadProperties()
{
loadPropertyItem(m_positionLinkedToMaster, m_elementsForPartLinkingOption);
loadPropertyItem(m_appearanceLinkedToMaster, m_elementsForPartLinkingOption);
loadPropertyItem(m_textLinkedToMaster, m_elementsForTextLinkingOption);
loadPropertyItem(m_excludeFromOtherParts, m_elementsForExcludeOption);

updateShowPartLinkingOption();
updateShowExcludeOption();
updateShowTextLinkingOption();
}

void PartsSettingsModel::resetProperties()
{
m_positionLinkedToMaster->resetToDefault();
m_appearanceLinkedToMaster->resetToDefault();
m_textLinkedToMaster->resetToDefault();
}

void PartsSettingsModel::onNotationChanged(const PropertyIdSet&, const StyleIdSet&)
Expand All @@ -100,6 +111,11 @@ PropertyItem* PartsSettingsModel::appearanceLinkedToMaster() const
return m_appearanceLinkedToMaster;
}

PropertyItem* PartsSettingsModel::textLinkedToMaster() const
{
return m_textLinkedToMaster;
}

PropertyItem* PartsSettingsModel::excludeFromOtherParts() const
{
return m_excludeFromOtherParts;
Expand All @@ -115,6 +131,11 @@ bool PartsSettingsModel::showExcludeOption() const
return m_showExcludeOption;
}

bool PartsSettingsModel::showTextLinkingOption() const
{
return m_showTextLinkingOption;
}

void PartsSettingsModel::updateShowPartLinkingOption()
{
bool showPartLinking = m_elementsForPartLinkingOption.size() > 0;
Expand All @@ -134,3 +155,13 @@ void PartsSettingsModel::updateShowExcludeOption()
emit showExcludeOptionChanged(m_showExcludeOption);
}
}

void PartsSettingsModel::updateShowTextLinkingOption()
{
bool showTextLink = m_elementsForTextLinkingOption.size() > 0;

if (m_showTextLinkingOption != showTextLink) {
m_showTextLinkingOption = showTextLink;
emit showTextLinkingOptionChanged(m_showTextLinkingOption);
}
}
9 changes: 9 additions & 0 deletions src/inspector/models/parts/partssettingsmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,29 @@ class PartsSettingsModel : public AbstractInspectorModel

Q_PROPERTY(PropertyItem * positionLinkedToMaster READ positionLinkedToMaster CONSTANT)
Q_PROPERTY(PropertyItem * appearanceLinkedToMaster READ appearanceLinkedToMaster CONSTANT)
Q_PROPERTY(PropertyItem * textLinkedToMaster READ textLinkedToMaster CONSTANT)
Q_PROPERTY(PropertyItem * excludeFromOtherParts READ excludeFromOtherParts CONSTANT)

Q_PROPERTY(bool showPartLinkingOption READ showPartLinkingOption NOTIFY showPartLinkingOptionChanged)
Q_PROPERTY(bool showExcludeOption READ showExcludeOption NOTIFY showExcludeOptionChanged)
Q_PROPERTY(bool showTextLinkingOption READ showTextLinkingOption NOTIFY showTextLinkingOptionChanged)

public:
explicit PartsSettingsModel(QObject* parent, IElementRepositoryService* repository);

PropertyItem* positionLinkedToMaster() const;
PropertyItem* appearanceLinkedToMaster() const;
PropertyItem* excludeFromOtherParts() const;
PropertyItem* textLinkedToMaster() const;

bool showPartLinkingOption() const;
bool showExcludeOption() const;
bool showTextLinkingOption() const;

signals:
void showPartLinkingOptionChanged(bool showPartsOption);
void showExcludeOptionChanged(bool excludeOption);
void showTextLinkingOptionChanged(bool showTextLink);

private:
void createProperties() override;
Expand All @@ -61,17 +66,21 @@ class PartsSettingsModel : public AbstractInspectorModel

void updateShowPartLinkingOption();
void updateShowExcludeOption();
void updateShowTextLinkingOption();

private:
PropertyItem* m_positionLinkedToMaster;
PropertyItem* m_appearanceLinkedToMaster;
PropertyItem* m_textLinkedToMaster;
PropertyItem* m_excludeFromOtherParts;

QList<EngravingItem*> m_elementsForPartLinkingOption;
QList<EngravingItem*> m_elementsForExcludeOption;
QList<EngravingItem*> m_elementsForTextLinkingOption;

bool m_showPartLinkingOption = false;
bool m_showExcludeOption = false;
bool m_showTextLinkingOption = false;
};
}

Expand Down
13 changes: 13 additions & 0 deletions src/inspector/view/qml/MuseScore/Inspector/parts/PartsSettings.qml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ InspectorSectionView {
propertyItem: root.model ? root.model.appearanceLinkedToMaster : null
text: qsTrc("inspector", "Style/appearance")
}

PropertyToggle {
id: textLinkedToMasterToggle

visible: root.model ? root.model.showTextLinkingOption : false

navigation.name: "Text linked to score"
navigation.panel: root.navigationPanel
navigation.row: appearanceLinkedToMasterToggle.navigationRow + 1

propertyItem: root.model ? root.model.textLinkedToMaster : null
text: qsTrc("inspector", "Text")
}
}

PropertyCheckBox {
Expand Down

0 comments on commit fc9b1e6

Please sign in to comment.