diff --git a/src/engraving/libmscore/cmd.cpp b/src/engraving/libmscore/cmd.cpp index 9e48077503d7..78cb63cae9c5 100644 --- a/src/engraving/libmscore/cmd.cpp +++ b/src/engraving/libmscore/cmd.cpp @@ -2847,7 +2847,7 @@ void Score::cmdAddParentheses() for (EngravingItem* el : selection().elements()) { if (el->type() == ElementType::NOTE) { Note* n = toNote(el); - n->addParentheses(); + n->setHeadHasParentheses(true); } else if (el->type() == ElementType::ACCIDENTAL) { Accidental* acc = toAccidental(el); acc->undoChangeProperty(Pid::ACCIDENTAL_BRACKET, int(AccidentalBracket::PARENTHESIS)); diff --git a/src/engraving/libmscore/note.cpp b/src/engraving/libmscore/note.cpp index 843d695889b8..1f774c376b5b 100644 --- a/src/engraving/libmscore/note.cpp +++ b/src/engraving/libmscore/note.cpp @@ -518,6 +518,8 @@ Note::~Note() qDeleteAll(_el); delete _tieFor; qDeleteAll(_dots); + _leftParenthesis = nullptr; + _rightParenthesis = nullptr; } Note::Note(const Note& n, bool link) @@ -1459,6 +1461,25 @@ void Note::read(XmlReader& e) } } } + + for (EngravingItem* item : _el) { + if (!item->isSymbol()) { + continue; + } + + Symbol* symbol = toSymbol(item); + SymId symbolId = symbol->sym(); + + if (symbolId == SymId::noteheadParenthesisLeft) { + _leftParenthesis = symbol; + } else if (symbolId == SymId::noteheadParenthesisRight) { + _rightParenthesis = symbol; + } + } + + if (_leftParenthesis && _rightParenthesis) { + _hasHeadParentheses = true; + } } //--------------------------------------------------------- @@ -1864,7 +1885,7 @@ EngravingItem* Note::drop(EditData& data) return ch->drop(data); break; case ActionIconType::PARENTHESES: - addParentheses(); + setHeadHasParentheses(true); break; default: break; @@ -1987,21 +2008,33 @@ EngravingItem* Note::drop(EditData& data) return 0; } -//--------------------------------------------------------- -// addParentheses -//--------------------------------------------------------- - -void Note::addParentheses() +void Note::setHeadHasParentheses(bool hasParentheses) { - Symbol* s = new Symbol(this); - s->setSym(SymId::noteheadParenthesisLeft); - s->setParent(this); - score()->undoAddElement(s); + if (hasParentheses == _hasHeadParentheses) { + return; + } + + _hasHeadParentheses = hasParentheses; - s = new Symbol(this); - s->setSym(SymId::noteheadParenthesisRight); - s->setParent(this); - score()->undoAddElement(s); + if (hasParentheses) { + if (!_leftParenthesis) { + _leftParenthesis = new Symbol(this); + _leftParenthesis->setSym(SymId::noteheadParenthesisLeft); + _leftParenthesis->setParent(this); + } + + if (!_rightParenthesis) { + _rightParenthesis = new Symbol(this); + _rightParenthesis->setSym(SymId::noteheadParenthesisRight); + _rightParenthesis->setParent(this); + } + + score()->undoAddElement(_leftParenthesis); + score()->undoAddElement(_rightParenthesis); + } else { + score()->undoRemoveElement(_leftParenthesis); + score()->undoRemoveElement(_rightParenthesis); + } } //--------------------------------------------------------- @@ -2925,6 +2958,8 @@ PropertyValue Note::getProperty(Pid propertyId) const return isSmall(); case Pid::MIRROR_HEAD: return userMirror(); + case Pid::HEAD_HAS_PARENTHESES: + return _hasHeadParentheses; case Pid::DOT_POSITION: return PropertyValue::fromValue(userDotPosition()); case Pid::HEAD_SCHEME: @@ -2986,6 +3021,9 @@ bool Note::setProperty(Pid propertyId, const PropertyValue& v) case Pid::MIRROR_HEAD: setUserMirror(v.value()); break; + case Pid::HEAD_HAS_PARENTHESES: + setHeadHasParentheses(v.toBool()); + break; case Pid::DOT_POSITION: setUserDotPosition(v.value()); triggerLayout(); @@ -3059,6 +3097,8 @@ PropertyValue Note::propertyDefault(Pid propertyId) const return false; case Pid::MIRROR_HEAD: return DirectionH::AUTO; + case Pid::HEAD_HAS_PARENTHESES: + return false; case Pid::DOT_POSITION: return DirectionV::AUTO; case Pid::HEAD_SCHEME: diff --git a/src/engraving/libmscore/note.h b/src/engraving/libmscore/note.h index 558245101868..fd79588ce7aa 100644 --- a/src/engraving/libmscore/note.h +++ b/src/engraving/libmscore/note.h @@ -203,6 +203,10 @@ class Note final : public EngravingItem Slide _attachedSlide; // slide which starts from note Slide* _relatedSlide = nullptr; // slide which goes to note + Symbol* _leftParenthesis = nullptr; + Symbol* _rightParenthesis = nullptr; + bool _hasHeadParentheses = false; + bool _isHammerOn = false; bool _harmonic = false; @@ -456,7 +460,7 @@ class Note final : public EngravingItem void setScore(Score* s) override; void setDotY(DirectionV); - void addParentheses(); + void setHeadHasParentheses(bool hasParentheses); static SymId noteHead(int direction, NoteHeadGroup, NoteHeadType, int tpc, Key key, NoteHeadScheme scheme); static SymId noteHead(int direction, NoteHeadGroup, NoteHeadType); diff --git a/src/engraving/libmscore/property.cpp b/src/engraving/libmscore/property.cpp index 728ade07307b..38ef77e1a60e 100644 --- a/src/engraving/libmscore/property.cpp +++ b/src/engraving/libmscore/property.cpp @@ -100,6 +100,7 @@ static constexpr PropertyMetaData propertyList[] = { { Pid::LEADING_SPACE, false, "leadingSpace", P_TYPE::SPATIUM, DUMMY_QT_TR_NOOP("propertyName", "leading space") }, { Pid::DISTRIBUTE, false, "distribute", P_TYPE::BOOL, DUMMY_QT_TR_NOOP("propertyName", "distributed") }, { Pid::MIRROR_HEAD, false, "mirror", P_TYPE::DIRECTION_H, DUMMY_QT_TR_NOOP("propertyName", "mirror") }, + { Pid::HEAD_HAS_PARENTHESES, false, "parentheses", P_TYPE::BOOL, DUMMY_QT_TR_NOOP("propertyName", "parentheses") }, { Pid::DOT_POSITION, false, "dotPosition", P_TYPE::DIRECTION_V, DUMMY_QT_TR_NOOP("propertyName", "dot position") }, { Pid::TUNING, false, "tuning", P_TYPE::REAL, DUMMY_QT_TR_NOOP("propertyName", "tuning") }, { Pid::PAUSE, true, "pause", P_TYPE::REAL, DUMMY_QT_TR_NOOP("propertyName", "pause") }, diff --git a/src/engraving/libmscore/property.h b/src/engraving/libmscore/property.h index 5c040976dcd9..c4f1a0399d89 100644 --- a/src/engraving/libmscore/property.h +++ b/src/engraving/libmscore/property.h @@ -103,6 +103,7 @@ enum class Pid { LEADING_SPACE, DISTRIBUTE, MIRROR_HEAD, + HEAD_HAS_PARENTHESES, DOT_POSITION, TUNING, PAUSE, diff --git a/src/framework/ui/view/iconcodes.h b/src/framework/ui/view/iconcodes.h index c4d0c0ca0841..1355c42272a9 100644 --- a/src/framework/ui/view/iconcodes.h +++ b/src/framework/ui/view/iconcodes.h @@ -214,6 +214,9 @@ class IconCode NOTE_HEAD_HALF = 0xF342, NOTE_HEAD_WHOLE = 0xF343, NOTE_HEAD_BREVIS = 0xF344, + NOTE_HEAD = 0xF42F, + NOTE_HEAD_PARENTHESES = 0xF430, + PLAY_REPEATS = 0xF345, BARLINE_WINGED = 0xF34C, BARLINE_UNWINGED = 0xF34D, diff --git a/src/inspector/models/notation/notes/noteheads/noteheadsettingsmodel.cpp b/src/inspector/models/notation/notes/noteheads/noteheadsettingsmodel.cpp index 9ff8c69bdb81..3f386317aed4 100644 --- a/src/inspector/models/notation/notes/noteheads/noteheadsettingsmodel.cpp +++ b/src/inspector/models/notation/notes/noteheads/noteheadsettingsmodel.cpp @@ -43,6 +43,8 @@ void NoteheadSettingsModel::createProperties() onPropertyValueChanged(pid, !isHeadHidden.toBool()); }); + m_isHeadSmall = buildPropertyItem(Ms::Pid::SMALL); + m_hasHeadParentheses = buildPropertyItem(Ms::Pid::HEAD_HAS_PARENTHESES); m_headDirection = buildPropertyItem(Ms::Pid::MIRROR_HEAD); m_headGroup = buildPropertyItem(Ms::Pid::HEAD_GROUP); m_headType = buildPropertyItem(Ms::Pid::HEAD_TYPE); @@ -68,6 +70,8 @@ void NoteheadSettingsModel::loadProperties() return !isVisible.toBool(); }); + loadPropertyItem(m_isHeadSmall); + loadPropertyItem(m_hasHeadParentheses); loadPropertyItem(m_headDirection); loadPropertyItem(m_headGroup); loadPropertyItem(m_headType); @@ -85,11 +89,12 @@ void NoteheadSettingsModel::loadProperties() void NoteheadSettingsModel::resetProperties() { m_isHeadHidden->resetToDefault(); + m_isHeadSmall->resetToDefault(); + m_hasHeadParentheses->resetToDefault(); m_headDirection->resetToDefault(); m_headGroup->resetToDefault(); m_headType->resetToDefault(); m_dotPosition->resetToDefault(); - m_horizontalOffset->resetToDefault(); m_verticalOffset->resetToDefault(); } @@ -99,6 +104,16 @@ PropertyItem* NoteheadSettingsModel::isHeadHidden() const return m_isHeadHidden; } +PropertyItem* NoteheadSettingsModel::isHeadSmall() const +{ + return m_isHeadSmall; +} + +PropertyItem* NoteheadSettingsModel::hasHeadParentheses() const +{ + return m_hasHeadParentheses; +} + PropertyItem* NoteheadSettingsModel::headDirection() const { return m_headDirection; diff --git a/src/inspector/models/notation/notes/noteheads/noteheadsettingsmodel.h b/src/inspector/models/notation/notes/noteheads/noteheadsettingsmodel.h index 377f27bf7a3e..259635dfdd92 100644 --- a/src/inspector/models/notation/notes/noteheads/noteheadsettingsmodel.h +++ b/src/inspector/models/notation/notes/noteheads/noteheadsettingsmodel.h @@ -30,6 +30,8 @@ class NoteheadSettingsModel : public AbstractInspectorModel Q_OBJECT Q_PROPERTY(PropertyItem * isHeadHidden READ isHeadHidden CONSTANT) + Q_PROPERTY(PropertyItem * isHeadSmall READ isHeadSmall CONSTANT) + Q_PROPERTY(PropertyItem * hasHeadParentheses READ hasHeadParentheses CONSTANT) Q_PROPERTY(PropertyItem * headDirection READ headDirection CONSTANT) Q_PROPERTY(PropertyItem * headGroup READ headGroup CONSTANT) Q_PROPERTY(PropertyItem * headType READ headType CONSTANT) @@ -41,6 +43,8 @@ class NoteheadSettingsModel : public AbstractInspectorModel explicit NoteheadSettingsModel(QObject* parent, IElementRepositoryService* repository); PropertyItem* isHeadHidden() const; + PropertyItem* isHeadSmall() const; + PropertyItem* hasHeadParentheses() const; PropertyItem* headDirection() const; PropertyItem* headGroup() const; PropertyItem* headType() const; @@ -48,14 +52,15 @@ class NoteheadSettingsModel : public AbstractInspectorModel PropertyItem* horizontalOffset() const; PropertyItem* verticalOffset() const; -protected: +private: void createProperties() override; void requestElements() override; void loadProperties() override; void resetProperties() override; -private: PropertyItem* m_isHeadHidden = nullptr; + PropertyItem* m_isHeadSmall = nullptr; + PropertyItem* m_hasHeadParentheses = nullptr; PropertyItem* m_headDirection = nullptr; PropertyItem* m_headGroup = nullptr; PropertyItem* m_headType = nullptr; diff --git a/src/inspector/models/propertyitem.cpp b/src/inspector/models/propertyitem.cpp index 86b44894f8c8..c224e8b89784 100644 --- a/src/inspector/models/propertyitem.cpp +++ b/src/inspector/models/propertyitem.cpp @@ -30,13 +30,6 @@ PropertyItem::PropertyItem(const Ms::Pid propertyId, QObject* parent) : QObject(parent), m_isVisible(true) { m_propertyId = propertyId; - - P_TYPE propertyType = Ms::propertyType(propertyId); - - if (propertyType != P_TYPE::COLOR) { - m_currentValue = 0; - m_defaultValue = 0; - } } void PropertyItem::fillValues(const QVariant& currentValue, const QVariant& defaultValue) diff --git a/src/inspector/view/qml/MuseScore/Inspector/notation/notes/HeadSettings.qml b/src/inspector/view/qml/MuseScore/Inspector/notation/notes/HeadSettings.qml index 34237d6639e7..be95d7348234 100644 --- a/src/inspector/view/qml/MuseScore/Inspector/notation/notes/HeadSettings.qml +++ b/src/inspector/view/qml/MuseScore/Inspector/notation/notes/HeadSettings.qml @@ -45,31 +45,61 @@ FocusableItem { spacing: 12 + FlatRadioButtonGroupPropertyView { + id: noteHeadParenthesesView + + titleText: qsTrc("inspector", "Notehead parentheses") + propertyItem: root.model ? root.model.hasHeadParentheses : null + + navigationPanel: root.navigationPanel + navigationRowStart: root.navigationRowStart + 1 + + model: [ + { iconCode: IconCode.NOTE_HEAD, value: false, title: qsTrc("inspector", "Normal notehead") }, + { iconCode: IconCode.NOTE_HEAD_PARENTHESES, value: true, title: qsTrc("inspector", "Notehead with parentheses") } + ] + } + + NoteheadGroupSelector { + id: noteHeadSection + + propertyItem: root.model ? root.model.headGroup : null + + navigationPanel: root.navigationPanel + navigationRowStart: noteHeadParenthesesView.navigationRowEnd + 1 + } + CheckBoxPropertyView { + id: hideNoteheadCheckBox + text: qsTrc("inspector", "Hide notehead") propertyItem: root.model ? root.model.isHeadHidden : null navigation.name: "HideNoteHeadBox" navigation.panel: root.navigationPanel - navigation.row: root.navigationRowStart + 1 + navigation.row: noteHeadSection.navigationRowEnd + 1 } - NoteheadGroupSelector { - id: noteHeadSection - propertyItem: root.model ? root.model.headGroup : null + CheckBoxPropertyView { + id: smallNoteheadCheckBox - navigationPanel: root.navigationPanel - navigationRowStart: root.navigationRowStart + 2 + text: qsTrc("inspector", "Small notehead") + propertyItem: root.model ? root.model.isHeadSmall : null + + navigation.name: "SmallNoteHeadBox" + navigation.panel: root.navigationPanel + navigation.row: hideNoteheadCheckBox.navigation.row + 1 } FlatRadioButtonGroupPropertyView { - id: dottedNotePositionSection + id: durationDotPosition + titleText: qsTrc("inspector", "Duration dot position") propertyItem: root.model ? root.model.dotPosition : null navigationName: "DottedNote" navigationPanel: root.navigationPanel - navigationRowStart: noteHeadSection.navigationRowEnd + 1 + navigationRowStart: smallNoteheadCheckBox.navigation.row + 1 model: [ { text: qsTrc("inspector", "Auto"), value: NoteHead.DOT_POSITION_AUTO, title: qsTrc("inspector", "Auto") }, @@ -80,6 +110,7 @@ FocusableItem { ExpandableBlank { id: showItem + isExpanded: false title: isExpanded ? qsTrc("inspector", "Show less") : qsTrc("inspector", "Show more") @@ -87,7 +118,7 @@ FocusableItem { width: parent.width navigation.panel: root.navigationPanel - navigation.row: dottedNotePositionSection.navigationRowEnd + 1 + navigation.row: durationDotPosition.navigationRowEnd + 1 contentItemComponent: Column { height: implicitHeight diff --git a/src/inspector/view/qml/MuseScore/Inspector/notation/notes/internal/NoteheadGroupSelector.qml b/src/inspector/view/qml/MuseScore/Inspector/notation/notes/internal/NoteheadGroupSelector.qml index ef46fd8cc442..46f7690e1b5a 100644 --- a/src/inspector/view/qml/MuseScore/Inspector/notation/notes/internal/NoteheadGroupSelector.qml +++ b/src/inspector/view/qml/MuseScore/Inspector/notation/notes/internal/NoteheadGroupSelector.qml @@ -31,7 +31,7 @@ import "../../../common" InspectorPropertyView { id: root - titleText: qsTrc("inspector", "Notehead group") + titleText: qsTrc("inspector", "Notehead type") navigationRowEnd: navigationRowStart + gridView.count + 1 /*menu button*/