diff --git a/src/engraving/compat/engravingcompat.cpp b/src/engraving/compat/engravingcompat.cpp index 96d2ee1a65ab5..c07cd84f01c9f 100644 --- a/src/engraving/compat/engravingcompat.cpp +++ b/src/engraving/compat/engravingcompat.cpp @@ -41,6 +41,10 @@ void EngravingCompat::doPreLayoutCompatIfNeeded(MasterScore* score) { int mscVersion = score->mscVersion(); + if (mscVersion < 470) { + adjustTextOffset(score); + } + if (mscVersion < 460) { resetMarkerLeftFontSize(score); resetRestVerticalOffsets(score); @@ -233,6 +237,39 @@ void EngravingCompat::adjustVBoxDistances(MasterScore* masterScore) } } +void EngravingCompat::adjustTextOffset(MasterScore* masterScore) +{ + auto doAdjustTextOffset = [](EngravingItem* item) { + if (!item->isTextBase()) { + return; + } + + TextBase* text = toTextBase(item); + + // Staff text, system text, and harp pedal diagrams are the only types which are attached to notes and weren't already + // placed with their left edges / centres / right edges aligned to the left / centre / right of the notehead + if (text->positionRelativeToNoteheadRest() && (text->isStaffText() || text->isSystemText() || text->isHarpPedalDiagram())) { + double mag = item->staff() ? item->staff()->staffMag(item) : 1.0; + double xAdj = item->symWidth(SymId::noteheadBlack) * mag; + + switch (text->position()) { + case AlignH::HCENTER: + text->setProperty(Pid::OFFSET, PointF(text->offset().x() - xAdj / 2, text->offset().y())); + break; + case AlignH::RIGHT: + text->setProperty(Pid::OFFSET, PointF(text->offset().x() - xAdj, text->offset().y())); + break; + default: + break; + } + } + }; + + for (Score* score : masterScore->scoreList()) { + score->scanElements(doAdjustTextOffset); + } +} + void EngravingCompat::doPostLayoutCompatIfNeeded(MasterScore* score) { bool needRelayout = false; diff --git a/src/engraving/compat/engravingcompat.h b/src/engraving/compat/engravingcompat.h index e4166b2afe3ab..1eaed5b90c578 100644 --- a/src/engraving/compat/engravingcompat.h +++ b/src/engraving/compat/engravingcompat.h @@ -40,6 +40,7 @@ class EngravingCompat static void resetMarkerLeftFontSize(MasterScore* masterScore); static void resetRestVerticalOffsets(MasterScore* masterScore); static void adjustVBoxDistances(MasterScore* masterScore); + static void adjustTextOffset(MasterScore* masterScore); static bool relayoutUserModifiedCrossStaffBeams(MasterScore* score); static bool resetHookHeightSign(MasterScore* masterScore); diff --git a/src/engraving/dom/dynamic.h b/src/engraving/dom/dynamic.h index f3f6136f02b24..9f3b3221c2c61 100644 --- a/src/engraving/dom/dynamic.h +++ b/src/engraving/dom/dynamic.h @@ -120,6 +120,8 @@ class Dynamic final : public TextBase bool isEditAllowed(EditData&) const override; + bool positionRelativeToNoteheadRest() const override { return true; } + Hairpin* leftHairpin() const { return m_leftHairpin; } Hairpin* rightHairpin() const { return m_rightHairpin; } diff --git a/src/engraving/dom/expression.h b/src/engraving/dom/expression.h index 4a8d90abb13ef..a3e78b4254e2d 100644 --- a/src/engraving/dom/expression.h +++ b/src/engraving/dom/expression.h @@ -59,5 +59,7 @@ class Expression final : public TextBase bool hasVoiceAssignmentProperties() const override { return true; } void reset() override; + + bool positionRelativeToNoteheadRest() const override { return true; } }; } diff --git a/src/engraving/dom/figuredbass.h b/src/engraving/dom/figuredbass.h index ab4099b25732c..9a30242fc8d16 100644 --- a/src/engraving/dom/figuredbass.h +++ b/src/engraving/dom/figuredbass.h @@ -291,6 +291,8 @@ class FiguredBass final : public TextBase bool setProperty(Pid propertyId, const PropertyValue&) override; PropertyValue propertyDefault(Pid) const override; + bool positionRelativeToNoteheadRest() const override { return true; } + size_t itemsCount() const { return m_items.size(); } void appendItem(FiguredBassItem* item) { m_items.push_back(item); } const std::vector& items() const { return m_items; } diff --git a/src/engraving/dom/fingering.h b/src/engraving/dom/fingering.h index 7b1f790b22af6..3589e7f0019eb 100644 --- a/src/engraving/dom/fingering.h +++ b/src/engraving/dom/fingering.h @@ -56,6 +56,8 @@ class Fingering final : public TextBase String accessibleInfo() const override; bool isOnCrossBeamSide() const; + + bool positionRelativeToNoteheadRest() const override { return false; } }; } // namespace mu::engraving #endif diff --git a/src/engraving/dom/guitarbend.h b/src/engraving/dom/guitarbend.h index a80bb8fc68284..9124d8a096dd0 100644 --- a/src/engraving/dom/guitarbend.h +++ b/src/engraving/dom/guitarbend.h @@ -266,5 +266,7 @@ class GuitarBendText final : public TextBase GuitarBendText* clone() const override { return new GuitarBendText(*this); } bool isEditable() const override { return false; } + + bool positionRelativeToNoteheadRest() const override { return false; } }; } diff --git a/src/engraving/dom/hammeronpulloff.h b/src/engraving/dom/hammeronpulloff.h index 50003ec45fc51..8f065a7f92d8a 100644 --- a/src/engraving/dom/hammeronpulloff.h +++ b/src/engraving/dom/hammeronpulloff.h @@ -54,6 +54,8 @@ class HammerOnPullOffText final : public TextBase PropertyValue propertyDefault(Pid id) const override; + bool positionRelativeToNoteheadRest() const override { return false; } + private: Chord* m_startChord = nullptr; Chord* m_endChord = nullptr; diff --git a/src/engraving/dom/harmony.cpp b/src/engraving/dom/harmony.cpp index ab2fcb6064933..477bd866159ff 100644 --- a/src/engraving/dom/harmony.cpp +++ b/src/engraving/dom/harmony.cpp @@ -1615,6 +1615,11 @@ PropertyValue Harmony::propertyDefault(Pid id) const return v; } +bool Harmony::positionRelativeToNoteheadRest() const +{ + return !parent()->isFretDiagram(); +} + //--------------------------------------------------------- // getPropertyStyle //--------------------------------------------------------- diff --git a/src/engraving/dom/harmony.h b/src/engraving/dom/harmony.h index bc7206c52bddf..49e064a713b43 100644 --- a/src/engraving/dom/harmony.h +++ b/src/engraving/dom/harmony.h @@ -289,6 +289,8 @@ class Harmony final : public TextBase bool setProperty(Pid propertyId, const PropertyValue& v) override; PropertyValue propertyDefault(Pid id) const override; + bool positionRelativeToNoteheadRest() const override; + double mag() const override; double bassScale() const { return m_bassScale; } diff --git a/src/engraving/dom/harppedaldiagram.h b/src/engraving/dom/harppedaldiagram.h index 10c872ad057fe..d5ba2e7c7c7cd 100644 --- a/src/engraving/dom/harppedaldiagram.h +++ b/src/engraving/dom/harppedaldiagram.h @@ -83,6 +83,8 @@ class HarpPedalDiagram final : public TextBase bool isTpcPlayable(int tpc); const std::set& playableTpcs() const { return m_playableTpcs; } + bool positionRelativeToNoteheadRest() const override { return true; } + private: std::array m_pedalState; diff --git a/src/engraving/dom/instrchange.h b/src/engraving/dom/instrchange.h index ac7ea7a7020c1..f1ccca6bc3d09 100644 --- a/src/engraving/dom/instrchange.h +++ b/src/engraving/dom/instrchange.h @@ -63,6 +63,8 @@ class InstrumentChange final : public TextBase PropertyValue propertyDefault(Pid) const override; + bool positionRelativeToNoteheadRest() const override { return true; } + bool placeMultiple() const override { return false; } private: diff --git a/src/engraving/dom/instrumentname.h b/src/engraving/dom/instrumentname.h index 2f0017ef8117b..5126fd452c47b 100644 --- a/src/engraving/dom/instrumentname.h +++ b/src/engraving/dom/instrumentname.h @@ -67,6 +67,8 @@ class InstrumentName final : public TextBase bool setProperty(Pid propertyId, const PropertyValue&) override; PropertyValue propertyDefault(Pid) const override; + bool positionRelativeToNoteheadRest() const override { return false; } + private: InstrumentNameType m_instrumentNameType = InstrumentNameType::LONG; diff --git a/src/engraving/dom/jump.h b/src/engraving/dom/jump.h index 101589d2dcc01..6e031d682a35b 100644 --- a/src/engraving/dom/jump.h +++ b/src/engraving/dom/jump.h @@ -76,6 +76,8 @@ class Jump final : public TextBase EngravingItem* prevSegmentElement() override; String accessibleInfo() const override; + bool positionRelativeToNoteheadRest() const override { return false; } + private: String m_jumpTo; String m_playUntil; diff --git a/src/engraving/dom/lyrics.h b/src/engraving/dom/lyrics.h index b7d0e88433955..68a8cc03ae39a 100644 --- a/src/engraving/dom/lyrics.h +++ b/src/engraving/dom/lyrics.h @@ -70,6 +70,8 @@ class Lyrics final : public TextBase bool isEditAllowed(EditData&) const override; void endEdit(EditData&) override; + bool positionRelativeToNoteheadRest() const override { return true; } + const Fraction& ticks() const { return m_ticks; } void setTicks(const Fraction& tick) { m_ticks = tick; } Fraction endTick() const; diff --git a/src/engraving/dom/marker.h b/src/engraving/dom/marker.h index 924e89d244ffe..8d8dedd10a93d 100644 --- a/src/engraving/dom/marker.h +++ b/src/engraving/dom/marker.h @@ -79,6 +79,8 @@ class Marker final : public TextBase EngravingItem* prevSegmentElement() override; String accessibleInfo() const override; + bool positionRelativeToNoteheadRest() const override { return false; } + bool centerOnSymbol() const { return m_centerOnSymbol; } void setCenterOnSymbol(bool val) { m_centerOnSymbol = val; } diff --git a/src/engraving/dom/measurenumberbase.h b/src/engraving/dom/measurenumberbase.h index f2a2ca4d61936..23361cd2dbf74 100644 --- a/src/engraving/dom/measurenumberbase.h +++ b/src/engraving/dom/measurenumberbase.h @@ -42,6 +42,7 @@ class MeasureNumberBase : public TextBase Measure* measure() const { return toMeasure(explicitParent()); } bool isEditable() const override { return false; } // The measure numbers' text should not be editable + bool positionRelativeToNoteheadRest() const override { return false; } }; } // namespace mu::engraving diff --git a/src/engraving/dom/playcounttext.h b/src/engraving/dom/playcounttext.h index 6a9cdb1639159..52e3b6475156b 100644 --- a/src/engraving/dom/playcounttext.h +++ b/src/engraving/dom/playcounttext.h @@ -51,6 +51,8 @@ class PlayCountText final : public TextBase bool setProperty(Pid propertyId, const PropertyValue&) override; PropertyValue propertyDefault(Pid propertyId) const override; + bool positionRelativeToNoteheadRest() const override { return false; } + private: friend class Factory; PlayCountText(Segment* parent, TextStyleType tid = TextStyleType::REPEAT_PLAY_COUNT); diff --git a/src/engraving/dom/rehearsalmark.h b/src/engraving/dom/rehearsalmark.h index 5cab8116e9a9b..61f3d315be8ba 100644 --- a/src/engraving/dom/rehearsalmark.h +++ b/src/engraving/dom/rehearsalmark.h @@ -58,6 +58,8 @@ class RehearsalMark final : public TextBase void styleChanged() override; + bool positionRelativeToNoteheadRest() const override { return false; } + private: void applyTypeStyle(); diff --git a/src/engraving/dom/stafftextbase.h b/src/engraving/dom/stafftextbase.h index b66075029e33d..87eee22bca47f 100644 --- a/src/engraving/dom/stafftextbase.h +++ b/src/engraving/dom/stafftextbase.h @@ -73,6 +73,8 @@ class StaffTextBase : public TextBase bool swing() const { return m_swing; } int capo() const { return m_capo; } + bool positionRelativeToNoteheadRest() const override { return true; } + private: String m_channelNames[4]; diff --git a/src/engraving/dom/sticking.h b/src/engraving/dom/sticking.h index 220ab43b0f9c1..71de351c2d79a 100644 --- a/src/engraving/dom/sticking.h +++ b/src/engraving/dom/sticking.h @@ -47,6 +47,8 @@ class Sticking final : public TextBase Measure* measure() const { return (Measure*)explicitParent()->explicitParent(); } bool isEditAllowed(EditData&) const override; + + bool positionRelativeToNoteheadRest() const override { return true; } }; } // namespace mu::engraving #endif diff --git a/src/engraving/dom/tapping.h b/src/engraving/dom/tapping.h index fb58cf2bfdab2..17d2873d16341 100644 --- a/src/engraving/dom/tapping.h +++ b/src/engraving/dom/tapping.h @@ -125,5 +125,7 @@ class TappingText final : public TextBase TappingText* clone() const override { return new TappingText(*this); } Color curColor(const rendering::PaintOptions& opt) const override; + + bool positionRelativeToNoteheadRest() const override { return true; } }; } // namespace mu::engraving diff --git a/src/engraving/dom/tempotext.h b/src/engraving/dom/tempotext.h index 027e15f0a1c98..aad81dc57e47b 100644 --- a/src/engraving/dom/tempotext.h +++ b/src/engraving/dom/tempotext.h @@ -93,6 +93,8 @@ class TempoText final : public TextBase PropertyValue propertyDefault(Pid id) const override; String accessibleInfo() const override; + bool positionRelativeToNoteheadRest() const override { return true; } + String tempoInfo() const; static constexpr double DEFAULT_SYM_SIZE_RATIO = 5.0 / 3.0; diff --git a/src/engraving/dom/text.cpp b/src/engraving/dom/text.cpp index 6850210d545d2..abab77d8d25a0 100644 --- a/src/engraving/dom/text.cpp +++ b/src/engraving/dom/text.cpp @@ -122,4 +122,13 @@ bool mu::engraving::Text::collectForDrawing() const { return !(parent() && parent()->isTuplet()); } + +bool Text::positionRelativeToNoteheadRest() const +{ + if (parent()->isBox() || parent()->isTuplet() || parent()->isSpannerSegment()) { + return false; + } + + return true; +} } diff --git a/src/engraving/dom/text.h b/src/engraving/dom/text.h index 38b8d3ea2bfe7..0adf9d441d2d0 100644 --- a/src/engraving/dom/text.h +++ b/src/engraving/dom/text.h @@ -51,6 +51,8 @@ class Text final : public TextBase VoiceAssignment voiceAssignment() const; bool collectForDrawing() const override; + + bool positionRelativeToNoteheadRest() const override; }; } // namespace mu::engraving diff --git a/src/engraving/dom/textbase.cpp b/src/engraving/dom/textbase.cpp index 49ba81301e977..f3b4157489745 100644 --- a/src/engraving/dom/textbase.cpp +++ b/src/engraving/dom/textbase.cpp @@ -1868,6 +1868,15 @@ void TextBase::layoutFrame(LayoutData* ldata) const ldata->setBbox(ldata->frame.adjusted(-w, -w, w, w)); } +// bool TextBase::positionRelativeToNoteheadRest() const +// { +// if (!parent()) { +// return false; +// } + +// return true; +// } + //--------------------------------------------------------- // lineSpacing //--------------------------------------------------------- diff --git a/src/engraving/dom/textbase.h b/src/engraving/dom/textbase.h index 44c404e4965ac..3856717b004b9 100644 --- a/src/engraving/dom/textbase.h +++ b/src/engraving/dom/textbase.h @@ -488,6 +488,8 @@ class TextBase : public EngravingItem //! At the moment it's: Text, Jump, Marker bool layoutToParentWidth() const { return m_layoutToParentWidth; } + virtual bool positionRelativeToNoteheadRest() const = 0; + void setVoiceAssignment(VoiceAssignment v) { m_voiceAssignment = v; } VoiceAssignment voiceAssignment() const { return m_voiceAssignment; } void setDirection(DirectionV v) { m_direction = v; } diff --git a/src/engraving/rendering/score/dynamicslayout.cpp b/src/engraving/rendering/score/dynamicslayout.cpp index b775ee6bd0fd1..53420907e542c 100644 --- a/src/engraving/rendering/score/dynamicslayout.cpp +++ b/src/engraving/rendering/score/dynamicslayout.cpp @@ -80,12 +80,6 @@ void DynamicsLayout::doLayoutDynamic(Dynamic* item, Dynamic::LayoutData* ldata, return; } - bool centerOnNote = item->centerOnNotehead() || (!item->centerOnNotehead() && item->position() == AlignH::HCENTER); - double mag = item->staff()->staffMag(item); - double noteHeadWidth = item->score()->noteHeadWidth() * mag; - - ldata->moveX(noteHeadWidth * (centerOnNote ? 0.5 : 1)); - if (!item->centerOnNotehead()) { return; } diff --git a/src/engraving/rendering/score/lyricslayout.cpp b/src/engraving/rendering/score/lyricslayout.cpp index 9f5cd546f65ae..178abb2542619 100644 --- a/src/engraving/rendering/score/lyricslayout.cpp +++ b/src/engraving/rendering/score/lyricslayout.cpp @@ -174,19 +174,16 @@ void LyricsLayout::layout(Lyrics* item, LayoutContext& ctx) } } - double nominalWidth = item->symWidth(SymId::noteheadBlack); if (item->position() == AlignH::HCENTER) { // // center under notehead, not origin // however, lyrics that are melismas or have verse numbers will be forced to left alignment // // center under note head - x += nominalWidth * .5 - centerAdjust * 0.5; + x += -centerAdjust * 0.5; } else if (item->position() == AlignH::LEFT) { // even for left aligned syllables, ignore leading verse numbers and/or punctuation x -= leftAdjust; - } else if (item->position() == AlignH::RIGHT) { - x += nominalWidth; } ldata->setPosX(x); diff --git a/src/engraving/rendering/score/textlayout.cpp b/src/engraving/rendering/score/textlayout.cpp index b811e84e572cf..70e2153c8c53e 100644 --- a/src/engraving/rendering/score/textlayout.cpp +++ b/src/engraving/rendering/score/textlayout.cpp @@ -192,6 +192,10 @@ void TextLayout::textHorizontalLayout(const TextBase* item, Shape& shape, double default: ASSERT_X("Lay out to parent width only valid for items with page or frame as parent"); } + } else if (item->positionRelativeToNoteheadRest()) { + // For items aligned to notehead/rests + double mag = item->staff() ? item->staff()->staffMag(item) : 1.0; + layoutWidth = item->symWidth(SymId::noteheadBlack) * mag; } // Position and alignment @@ -217,6 +221,7 @@ void TextLayout::textHorizontalLayout(const TextBase* item, Shape& shape, double shape.add(textBlock.shape().translated(PointF(0.0, textBlock.y()))); continue; } + // Align relative to the longest line AlignH alignH = item->align().horizontal; if (alignH == AlignH::HCENTER) { diff --git a/src/engraving/rendering/score/tlayout.cpp b/src/engraving/rendering/score/tlayout.cpp index dc43114444406..4b107c6dd9d94 100644 --- a/src/engraving/rendering/score/tlayout.cpp +++ b/src/engraving/rendering/score/tlayout.cpp @@ -5319,27 +5319,6 @@ void TLayout::layoutSticking(const Sticking* item, Sticking::LayoutData* ldata) LAYOUT_CALL_ITEM(item); TextLayout::layoutBaseTextBase(item, ldata); - AlignH itemPosition = item->position(); - if (itemPosition != AlignH::LEFT) { - const Segment* seg = item->segment(); - const Chord* chord = nullptr; - track_idx_t sTrack = trackZeroVoice(item->track()); - track_idx_t eTrack = sTrack + VOICES; - for (track_idx_t track = sTrack; track < eTrack; ++track) { - EngravingItem* el = seg->element(track); - if (el && el->isChord()) { - chord = toChord(el); - break; - } - } - - if (chord) { - const Note* refNote = item->placeAbove() ? chord->upNote() : chord->downNote(); - double noteWidth = refNote->ldata()->bbox().width(); - ldata->moveX(itemPosition == AlignH::HCENTER ? 0.5 * noteWidth : noteWidth); - } - } - if (item->autoplace() && item->explicitParent()) { const Segment* s = toSegment(item->explicitParent()); const Measure* m = s->measure(); diff --git a/src/inspector/qml/MuseScore/Inspector/text/TextInspectorView.qml b/src/inspector/qml/MuseScore/Inspector/text/TextInspectorView.qml index 199df60728282..ab91527c1deec 100644 --- a/src/inspector/qml/MuseScore/Inspector/text/TextInspectorView.qml +++ b/src/inspector/qml/MuseScore/Inspector/text/TextInspectorView.qml @@ -165,226 +165,233 @@ InspectorSectionView { } } - InspectorPropertyView { - id: alignmentSection - titleText: qsTrc("inspector", "Alignment") - propertyItem: root.model ? root.model.horizontalAlignment : null - - navigationName: "AlignmentMenu" - navigationPanel: root.navigationPanel - navigationRowStart: sizeSection.navigationRowEnd + 1 - navigationRowEnd: verticalAlignmentButtonList.navigationRowEnd - - isModified: root.model ? (root.model.horizontalAlignment.isModified - || root.model.verticalAlignment.isModified) : false - - onRequestResetToDefault: { - if (root.model) { - root.model.horizontalAlignment.resetToDefault() - root.model.verticalAlignment.resetToDefault() - } - } + Column { + height: implicitHeight + width: parent.width - onRequestApplyToStyle: { - if (root.model) { - root.model.horizontalAlignment.applyToStyle() - root.model.verticalAlignment.applyToStyle() - } - } + spacing: 8 - Item { - height: childrenRect.height - width: parent.width + InspectorPropertyView { + id: alignmentSection + titleText: qsTrc("inspector", "Alignment") + propertyItem: root.model ? root.model.horizontalAlignment : null - RadioButtonGroup { - enabled: root.model ? root.model.isHorizontalAlignmentAvailable : false - id: horizontalAlignmentButtonList + navigationName: "AlignmentMenu" + navigationPanel: root.navigationPanel + navigationRowStart: sizeSection.navigationRowEnd + 1 + navigationRowEnd: verticalAlignmentButtonList.navigationRowEnd - property int navigationRowStart: alignmentSection.navigationRowStart + 1 - property int navigationRowEnd: navigationRowStart + count + isModified: root.model ? (root.model.horizontalAlignment.isModified + || root.model.verticalAlignment.isModified) : false - anchors.left: parent.left - anchors.right: parent.horizontalCenter - anchors.rightMargin: 2 + onRequestResetToDefault: { + if (root.model) { + root.model.horizontalAlignment.resetToDefault() + root.model.verticalAlignment.resetToDefault() + } + } - height: 30 + onRequestApplyToStyle: { + if (root.model) { + root.model.horizontalAlignment.applyToStyle() + root.model.verticalAlignment.applyToStyle() + } + } - model: [ - { - iconCode: IconCode.TEXT_ALIGN_LEFT, - value: TextTypes.FONT_ALIGN_H_LEFT, - title: qsTrc("inspector", "Align left"), - description: qsTrc("inspector", "Align left edge of text to reference point") - }, - { - iconCode: IconCode.TEXT_ALIGN_CENTER, - value: TextTypes.FONT_ALIGN_H_CENTER, - title: qsTrc("inspector", "Align center"), - description: qsTrc("inspector", "Align horizontal center of text to reference point") - }, - { - iconCode: IconCode.TEXT_ALIGN_RIGHT, - value: TextTypes.FONT_ALIGN_H_RIGHT, - title: qsTrc("inspector", "Align right"), - description: qsTrc("inspector", "Align right edge of text to reference point") - }, - { - iconCode: IconCode.TEXT_ALIGN_JUSTIFY, - value: TextTypes.FONT_ALIGN_H_JUSTIFY, - title: qsTrc("inspector", "Justify"), - description: qsTrc("inspector", "Justify text to fill the available width") + Item { + height: childrenRect.height + width: parent.width + + RadioButtonGroup { + enabled: root.model ? root.model.isHorizontalAlignmentAvailable : false + id: horizontalAlignmentButtonList + + property int navigationRowStart: alignmentSection.navigationRowStart + 1 + property int navigationRowEnd: navigationRowStart + count + + anchors.left: parent.left + anchors.right: parent.horizontalCenter + anchors.rightMargin: 2 + + height: 30 + + model: [ + { + iconCode: IconCode.TEXT_ALIGN_LEFT, + value: TextTypes.FONT_ALIGN_H_LEFT, + title: qsTrc("inspector", "Align left"), + description: qsTrc("inspector", "Left-align text within its bounding box") + }, + { + iconCode: IconCode.TEXT_ALIGN_CENTER, + value: TextTypes.FONT_ALIGN_H_CENTER, + title: qsTrc("inspector", "Align center"), + description: qsTrc("inspector", "Horizontally center text within its bounding box") + }, + { + iconCode: IconCode.TEXT_ALIGN_RIGHT, + value: TextTypes.FONT_ALIGN_H_RIGHT, + title: qsTrc("inspector", "Align right"), + description: qsTrc("inspector", "Right-align text within its bounding box") + }, + { + iconCode: IconCode.TEXT_ALIGN_JUSTIFY, + value: TextTypes.FONT_ALIGN_H_JUSTIFY, + title: qsTrc("inspector", "Justify"), + description: qsTrc("inspector", "Justify text to fill the available width") + } + ] + + delegate: FlatRadioButton { + required iconCode + required property int value + required property string title + required property string description + required property int index + + navigation.panel: root.navigationPanel + navigation.name: "HAlign" + index + navigation.row: horizontalAlignmentButtonList.navigationRowStart + index + navigation.accessible.name: title + navigation.accessible.description: description + + toolTipTitle: title + toolTipDescription: description + + width: 30 + transparent: true + + checked: root.model && !root.model.horizontalAlignment.isUndefined && (root.model.horizontalAlignment.value === value) + onToggled: { + root.model.horizontalAlignment.value = value + } } - ] - - delegate: FlatRadioButton { - required iconCode - required property int value - required property string title - required property string description - required property int index - - navigation.panel: root.navigationPanel - navigation.name: "HAlign" + index - navigation.row: horizontalAlignmentButtonList.navigationRowStart + index - navigation.accessible.name: title - navigation.accessible.description: description - - toolTipTitle: title - toolTipDescription: description - - width: 30 - transparent: true + } - checked: root.model && !root.model.horizontalAlignment.isUndefined && (root.model.horizontalAlignment.value === value) - onToggled: { - root.model.horizontalAlignment.value = value + RadioButtonGroup { + enabled: root.model ? root.model.isHorizontalAlignmentAvailable : false + id: positionButtonList + + property int navigationRowStart: horizontalAlignmentButtonList.navigationRowEnd + 1 + property int navigationRowEnd: navigationRowStart + count + + anchors.leftMargin: 2 + anchors.right: parent.right + + height: 30 + + model: [ + { + iconCode: root.model && root.model.usePositionRelativeToLine ? IconCode.ALIGN_LEFT : IconCode.NOTE_ALIGN_LEFT, + value: CommonTypes.LEFT, + title: root.model ? root.model.leftPositionText : "", + description: "" + }, + { + iconCode: root.model && root.model.usePositionRelativeToLine ? IconCode.ALIGN_HORIZONTAL_CENTER : IconCode.NOTE_ALIGN_CENTER, + value: + CommonTypes.HCENTER, + title: root.model ? root.model.centerPositionText : "", + description: "" + }, + { + iconCode: root.model && root.model.usePositionRelativeToLine ? IconCode.ALIGN_RIGHT : IconCode.NOTE_ALIGN_RIGHT, + value: CommonTypes.RIGHT, + title: root.model ? root.model.rightPositionText : "", + description: "" + } + ] + + delegate: FlatRadioButton { + required iconCode + required property int value + required property string title + required property string description + required property int index + + navigation.panel: root.navigationPanel + navigation.name: "HAlign" + index + navigation.row: positionButtonList.navigationRowStart + index + navigation.accessible.name: title + navigation.accessible.description: description + + toolTipTitle: title + toolTipDescription: description + + width: 30 + transparent: true + + checked: root.model && !root.model.horizontalPosition.isUndefined && (root.model.horizontalPosition.value === value) + onToggled: { + root.model.horizontalPosition.value = value + } } } } + } - RadioButtonGroup { - id: verticalAlignmentButtonList - - property int navigationRowStart: horizontalAlignmentButtonList.navigationRowEnd + 1 - property int navigationRowEnd: navigationRowStart + count - - anchors.left: parent.horizontalCenter - anchors.leftMargin: 2 - anchors.right: parent.right - - height: 30 - - model: [ - { - iconCode: IconCode.TEXT_ALIGN_TOP, - value: TextTypes.FONT_ALIGN_V_TOP, - title: qsTrc("inspector", "Align top"), - description: qsTrc("inspector", "Align top edge of text to reference point") - }, - { - iconCode: IconCode.TEXT_ALIGN_MIDDLE, - value: TextTypes.FONT_ALIGN_V_CENTER, - title: qsTrc("inspector", "Align middle"), - description: qsTrc("inspector", "Align vertical center of text to reference point") - }, - { - iconCode: IconCode.TEXT_ALIGN_BOTTOM, - value: TextTypes.FONT_ALIGN_V_BOTTOM, - title:qsTrc("inspector", "Align bottom"), - description: qsTrc("inspector", "Align bottom edge of text to reference point") - }, - { - iconCode: IconCode.TEXT_ALIGN_BASELINE, - value: TextTypes.FONT_ALIGN_V_BASELINE, - title: qsTrc("inspector", "Align baseline"), - description: qsTrc("inspector", "Align baseline of text to reference point") - } - ] - - delegate: FlatRadioButton { - required iconCode - required property int value - required property string title - required property string description - required property int index - - navigation.panel: root.navigationPanel - navigation.name: "VAlign" + index - navigation.row: verticalAlignmentButtonList.navigationRowStart + index - navigation.accessible.name: title - navigation.accessible.description: description + RadioButtonGroup { + id: verticalAlignmentButtonList - toolTipTitle: title - toolTipDescription: description + property int navigationRowStart: positionButtonList.navigationRowEnd + 1 + property int navigationRowEnd: navigationRowStart + count - width: 30 - transparent: true + anchors.left: parent.left + anchors.right: parent.horizontalCenter + anchors.rightMargin: 2 - checked: root.model && !root.model.verticalAlignment.isUndefined && (root.model.verticalAlignment.value === value) - onToggled: { - root.model.verticalAlignment.value = value - } + height: 30 + + model: [ + { + iconCode: IconCode.TEXT_ALIGN_TOP, + value: TextTypes.FONT_ALIGN_V_TOP, + title: qsTrc("inspector", "Align top"), + description: qsTrc("inspector", "Align top edge of text to reference point") + }, + { + iconCode: IconCode.TEXT_ALIGN_MIDDLE, + value: TextTypes.FONT_ALIGN_V_CENTER, + title: qsTrc("inspector", "Align middle"), + description: qsTrc("inspector", "Align vertical center of text to reference point") + }, + { + iconCode: IconCode.TEXT_ALIGN_BOTTOM, + value: TextTypes.FONT_ALIGN_V_BOTTOM, + title:qsTrc("inspector", "Align bottom"), + description: qsTrc("inspector", "Align bottom edge of text to reference point") + }, + { + iconCode: IconCode.TEXT_ALIGN_BASELINE, + value: TextTypes.FONT_ALIGN_V_BASELINE, + title: qsTrc("inspector", "Align baseline"), + description: qsTrc("inspector", "Align baseline of text to reference point") + } + ] + + delegate: FlatRadioButton { + required iconCode + required property int value + required property string title + required property string description + required property int index + + navigation.panel: root.navigationPanel + navigation.name: "VAlign" + index + navigation.row: verticalAlignmentButtonList.navigationRowStart + index + navigation.accessible.name: title + navigation.accessible.description: description + + toolTipTitle: title + toolTipDescription: description + + width: 30 + transparent: true + + checked: root.model && !root.model.verticalAlignment.isUndefined && (root.model.verticalAlignment.value === value) + onToggled: { + root.model.verticalAlignment.value = value } - } - } - } - - RadioButtonGroup { - enabled: root.model ? root.model.isHorizontalAlignmentAvailable : false - id: positionButtonList - - property int navigationRowStart: alignmentSection.navigationRowEnd + 1 - property int navigationRowEnd: navigationRowStart + count - - anchors.left: parent.left - anchors.right: parent.horizontalCenter - anchors.rightMargin: 2 - - height: 30 - - model: [ - { - iconCode: root.model && root.model.usePositionRelativeToLine ? IconCode.ALIGN_LEFT : IconCode.NOTE_ALIGN_LEFT, - value: CommonTypes.LEFT, - title: qsTrc("inspector", "Align left"), - description: qsTrc("inspector", "Align left edge of text to reference point") - }, - { - iconCode: root.model && root.model.usePositionRelativeToLine ? IconCode.ALIGN_HORIZONTAL_CENTER : IconCode.NOTE_ALIGN_CENTER, - value: CommonTypes.HCENTER, - title: qsTrc("inspector", "Align center"), - description: qsTrc("inspector", "Align horizontal center of text to reference point") - }, - { - iconCode: root.model && root.model.usePositionRelativeToLine ? IconCode.ALIGN_RIGHT : IconCode.NOTE_ALIGN_RIGHT, - value: CommonTypes.RIGHT, - title: qsTrc("inspector", "Align right"), - description: qsTrc("inspector", "Align right edge of text to reference point") - } - ] - - delegate: FlatRadioButton { - required iconCode - required property int value - required property string title - required property string description - required property int index - - navigation.panel: root.navigationPanel - navigation.name: "HAlign" + index - navigation.row: positionButtonList.navigationRowStart + index - navigation.accessible.name: title - navigation.accessible.description: description - - toolTipTitle: title - toolTipDescription: description - - width: 30 - transparent: true - - checked: root.model && !root.model.horizontalPosition.isUndefined && (root.model.horizontalPosition.value === value) - onToggled: { - root.model.horizontalPosition.value = value } } } @@ -395,7 +402,7 @@ InspectorSectionView { navigation.panel: root.navigationPanel navigation.name: "Insert special characters" - navigation.row: positionButtonList.navigationRowEnd + 1 + navigation.row: verticalAlignmentButtonList.navigationRowEnd + 1 text: qsTrc("inspector", "Insert special characters") diff --git a/src/inspector/qml/MuseScore/Inspector/text/textsettingsmodel.cpp b/src/inspector/qml/MuseScore/Inspector/text/textsettingsmodel.cpp index 41d8dc8b5507f..45a4412be5f9d 100644 --- a/src/inspector/qml/MuseScore/Inspector/text/textsettingsmodel.cpp +++ b/src/inspector/qml/MuseScore/Inspector/text/textsettingsmodel.cpp @@ -272,6 +272,9 @@ void TextSettingsModel::loadProperties(const PropertyIdSet& propertyIdSet) updateIsLineSpacingAvailable(); updateIsPositionAvailable(); updateUsePositionRelativeToLine(); + updateLeftPositionText(); + updateCenterPositionText(); + updateRightPositionText(); } bool TextSettingsModel::isTextLineText() const @@ -498,6 +501,21 @@ bool TextSettingsModel::usePositionRelativeToLine() const return m_usePositionRelativeToLine; } +QString TextSettingsModel::leftPositionText() const +{ + return m_leftPositionText; +} + +QString TextSettingsModel::centerPositionText() const +{ + return m_centerPositionText; +} + +QString TextSettingsModel::rightPositionText() const +{ + return m_rightPositionText; +} + void TextSettingsModel::setAreTextPropertiesAvailable(bool areTextPropertiesAvailable) { if (m_areTextPropertiesAvailable == areTextPropertiesAvailable) { @@ -598,6 +616,36 @@ void TextSettingsModel::setUsePositionRelativeToLineChanged(bool usePositionRela emit usePositionRelativeToLineChanged(m_usePositionRelativeToLine); } +void TextSettingsModel::setLeftPositionText(QString leftPositionText) +{ + if (leftPositionText == m_leftPositionText) { + return; + } + + m_leftPositionText = leftPositionText; + emit leftPositionTextChanged(m_leftPositionText); +} + +void TextSettingsModel::setCenterPositionText(QString centerPositionText) +{ + if (centerPositionText == m_centerPositionText) { + return; + } + + m_centerPositionText = centerPositionText; + emit centerPositionTextChanged(m_centerPositionText); +} + +void TextSettingsModel::setRightPositionText(QString rightPositionText) +{ + if (rightPositionText == m_rightPositionText) { + return; + } + + m_rightPositionText = rightPositionText; + emit rightPositionTextChanged(m_rightPositionText); +} + void TextSettingsModel::updateFramePropertiesAvailability() { bool isFrameVisible = static_cast(m_frameType->value().toInt()) @@ -703,11 +751,7 @@ void TextSettingsModel::updateUsePositionRelativeToLine() { bool useBarlineIcon = false; for (EngravingItem* item : m_elementList) { - bool useBl = item->isMarker() || item->isJump() || item->isRehearsalMark() || item->isMeasureNumber(); - bool harmonyUseBl = item->isHarmony() && item->parent()->isFretDiagram(); - bool textUseBl = item->isText() && (item->parent()->isBox() || item->parent()->isVoltaSegment()); - - if (useBl || harmonyUseBl || textUseBl) { + if (!toTextBase(item)->positionRelativeToNoteheadRest()) { useBarlineIcon = true; } } @@ -715,6 +759,60 @@ void TextSettingsModel::updateUsePositionRelativeToLine() setUsePositionRelativeToLineChanged(useBarlineIcon); } +void TextSettingsModel::updateLeftPositionText() +{ + for (EngravingItem* item : m_elementList) { + if (!item->parent()) { + continue; + } + + if (item->parent()->isBox()) { + setLeftPositionText(muse::qtrc("inspector", "Left-align text box within frame")); + } else if (toTextBase(item)->positionRelativeToNoteheadRest()) { + setLeftPositionText(muse::qtrc("inspector", "Left-align text box to note/rest")); + } else { + setLeftPositionText(muse::qtrc("inspector", "Left-align text box to barline")); + } + return; + } +} + +void TextSettingsModel::updateCenterPositionText() +{ + for (EngravingItem* item : m_elementList) { + if (!item->parent()) { + continue; + } + + if (item->parent()->isBox()) { + setCenterPositionText(muse::qtrc("inspector", "Horizontally center text box within frame")); + } else if (toTextBase(item)->positionRelativeToNoteheadRest()) { + setCenterPositionText(muse::qtrc("inspector", "Horizontally center text box to note/rest")); + } else { + setCenterPositionText(muse::qtrc("inspector", "Horizontally center text box to barline")); + } + return; + } +} + +void TextSettingsModel::updateRightPositionText() +{ + for (EngravingItem* item : m_elementList) { + if (!item->parent()) { + continue; + } + + if (item->parent()->isBox()) { + setRightPositionText(muse::qtrc("inspector", "Right-align text box within frame")); + } else if (toTextBase(item)->positionRelativeToNoteheadRest()) { + setRightPositionText(muse::qtrc("inspector", "Right-align text box to note/rest")); + } else { + setRightPositionText(muse::qtrc("inspector", "Right-align text box to barline")); + } + return; + } +} + void TextSettingsModel::propertyChangedCallback(const engraving::Pid propertyId, const QVariant& newValue) { setPropertyValue(m_elementList, propertyId, newValue); diff --git a/src/inspector/qml/MuseScore/Inspector/text/textsettingsmodel.h b/src/inspector/qml/MuseScore/Inspector/text/textsettingsmodel.h index 73aeea3350fbb..e210787a1a8ab 100644 --- a/src/inspector/qml/MuseScore/Inspector/text/textsettingsmodel.h +++ b/src/inspector/qml/MuseScore/Inspector/text/textsettingsmodel.h @@ -74,6 +74,9 @@ class TextSettingsModel : public AbstractInspectorModel Q_PROPERTY(bool isPositionAvailable READ isPositionAvailable NOTIFY isPositionAvailableChanged) Q_PROPERTY(bool usePositionRelativeToLine READ usePositionRelativeToLine NOTIFY usePositionRelativeToLineChanged) + Q_PROPERTY(QString leftPositionText READ leftPositionText NOTIFY leftPositionTextChanged) + Q_PROPERTY(QString centerPositionText READ centerPositionText NOTIFY centerPositionTextChanged) + Q_PROPERTY(QString rightPositionText READ rightPositionText NOTIFY rightPositionTextChanged) public: explicit TextSettingsModel(QObject* parent, IElementRepositoryService* repository, bool isTextLineText); @@ -123,6 +126,9 @@ class TextSettingsModel : public AbstractInspectorModel bool isLineSpacingAvailable() const; bool isPositionAvailable() const; bool usePositionRelativeToLine() const; + QString leftPositionText() const; + QString centerPositionText() const; + QString rightPositionText() const; public slots: void setAreTextPropertiesAvailable(bool areTextPropertiesAvailable); @@ -135,6 +141,9 @@ public slots: void setIsLineSpacingAvailable(bool isLineSpacingAvailable); void setIsPositionAvailableChanged(bool isPositionAvailable); void setUsePositionRelativeToLineChanged(bool usePositionRelativeToLine); + void setLeftPositionText(QString leftPositionText); + void setCenterPositionText(QString centerPositionText); + void setRightPositionText(QString rightPositionText); signals: void textStylesChanged(); @@ -149,6 +158,9 @@ public slots: void isLineSpacingAvailableChanged(bool isLineSpacingAvailable); void isPositionAvailableChanged(bool isPositionAvailable); void usePositionRelativeToLineChanged(bool positionRelativeToLine); + void leftPositionTextChanged(QString leftPositionText); + void centerPositionTextChanged(QString centerPositionText); + void rightPositionTextChanged(QString rightPositionText); private: bool isTextEditingStarted() const; @@ -164,6 +176,9 @@ public slots: void updateIsLineSpacingAvailable(); void updateIsPositionAvailable(); void updateUsePositionRelativeToLine(); + void updateLeftPositionText(); + void updateCenterPositionText(); + void updateRightPositionText(); void propertyChangedCallback(const mu::engraving::Pid propertyId, const QVariant& newValue); void propertyResetCallback(const mu::engraving::Pid propertyId); @@ -207,5 +222,9 @@ public slots: bool m_isPositionAvailable = false; bool m_usePositionRelativeToLine = false; + + QString m_leftPositionText; + QString m_centerPositionText; + QString m_rightPositionText; }; } diff --git a/src/notation/view/widgets/alignSelect.cpp b/src/notation/view/widgets/alignSelect.cpp index 76b0424cac9fe..e43ddd81bf62a 100644 --- a/src/notation/view/widgets/alignSelect.cpp +++ b/src/notation/view/widgets/alignSelect.cpp @@ -34,17 +34,22 @@ AlignSelect::AlignSelect(QWidget* parent) { setupUi(this); - g1 = new QButtonGroup(this); - g1->addButton(alignLeft); - g1->addButton(alignHCenter); - g1->addButton(alignRight); - g1->addButton(alignJustify); - - g2 = new QButtonGroup(this); - g2->addButton(alignTop); - g2->addButton(alignVCenter); - g2->addButton(alignBaseline); - g2->addButton(alignBottom); + horizontalAlignButtons = new QButtonGroup(this); + horizontalAlignButtons->addButton(alignLeft); + horizontalAlignButtons->addButton(alignHCenter); + horizontalAlignButtons->addButton(alignRight); + horizontalAlignButtons->addButton(alignJustify); + + verticalAlignButtons = new QButtonGroup(this); + verticalAlignButtons->addButton(alignTop); + verticalAlignButtons->addButton(alignVCenter); + verticalAlignButtons->addButton(alignBaseline); + verticalAlignButtons->addButton(alignBottom); + + positionButtons = new QButtonGroup(this); + positionButtons->addButton(positionLeft); + positionButtons->addButton(positionHCenter); + positionButtons->addButton(positionRight); WidgetUtils::setWidgetIcon(alignLeft, IconCode::Code::TEXT_ALIGN_LEFT); WidgetUtils::setWidgetIcon(alignRight, IconCode::Code::TEXT_ALIGN_RIGHT); @@ -54,9 +59,13 @@ AlignSelect::AlignSelect(QWidget* parent) WidgetUtils::setWidgetIcon(alignTop, IconCode::Code::TEXT_ALIGN_TOP); WidgetUtils::setWidgetIcon(alignBaseline, IconCode::Code::TEXT_ALIGN_BASELINE); WidgetUtils::setWidgetIcon(alignBottom, IconCode::Code::TEXT_ALIGN_BOTTOM); + WidgetUtils::setWidgetIcon(positionLeft, IconCode::Code::ALIGN_LEFT); + WidgetUtils::setWidgetIcon(positionRight, IconCode::Code::ALIGN_RIGHT); + WidgetUtils::setWidgetIcon(positionHCenter, IconCode::Code::ALIGN_HORIZONTAL_CENTER); - connect(g1, &QButtonGroup::buttonToggled, this, &AlignSelect::_alignChanged); - connect(g2, &QButtonGroup::buttonToggled, this, &AlignSelect::_alignChanged); + connect(horizontalAlignButtons, &QButtonGroup::buttonToggled, this, &AlignSelect::_alignChanged); + connect(verticalAlignButtons, &QButtonGroup::buttonToggled, this, &AlignSelect::_alignChanged); + connect(positionButtons, &QButtonGroup::buttonToggled, this, &AlignSelect::_positionChanged); } void AlignSelect::_alignChanged() @@ -64,6 +73,11 @@ void AlignSelect::_alignChanged() emit alignChanged(align()); } +void AlignSelect::_positionChanged() +{ + emit positionChanged(position()); +} + mu::engraving::Align AlignSelect::align() const { mu::engraving::Align a = { mu::engraving::AlignH::LEFT, mu::engraving::AlignV::TOP }; @@ -84,6 +98,17 @@ mu::engraving::Align AlignSelect::align() const return a; } +mu::engraving::AlignH AlignSelect::position() const +{ + mu::engraving::AlignH position = mu::engraving::AlignH::LEFT; + if (positionHCenter->isChecked()) { + position = mu::engraving::AlignH::HCENTER; + } else if (positionRight->isChecked()) { + position = mu::engraving::AlignH::RIGHT; + } + return position; +} + void AlignSelect::setAlign(mu::engraving::Align a) { blockAlign(true); @@ -108,8 +133,26 @@ void AlignSelect::setAlign(mu::engraving::Align a) blockAlign(false); } +void AlignSelect::setPosition(mu::engraving::AlignH a) +{ + blockPosition(true); + if (a == mu::engraving::AlignH::HCENTER) { + positionHCenter->setChecked(true); + } else if (a == mu::engraving::AlignH::RIGHT) { + positionRight->setChecked(true); + } else { + positionLeft->setChecked(true); + } + blockPosition(false); +} + void AlignSelect::blockAlign(bool val) { - g1->blockSignals(val); - g2->blockSignals(val); + horizontalAlignButtons->blockSignals(val); + verticalAlignButtons->blockSignals(val); +} + +void AlignSelect::blockPosition(bool val) +{ + positionButtons->blockSignals(val); } diff --git a/src/notation/view/widgets/alignSelect.h b/src/notation/view/widgets/alignSelect.h index 732b4e36cab1c..beb228e3c1418 100644 --- a/src/notation/view/widgets/alignSelect.h +++ b/src/notation/view/widgets/alignSelect.h @@ -34,19 +34,26 @@ class AlignSelect : public QWidget, public Ui::AlignSelect, public muse::Injecta public: AlignSelect(QWidget* parent); mu::engraving::Align align() const; + mu::engraving::AlignH position() const; + void setAlign(mu::engraving::Align); + void setPosition(mu::engraving::AlignH); signals: void alignChanged(mu::engraving::Align); + void positionChanged(mu::engraving::AlignH); private: - QButtonGroup* g1; - QButtonGroup* g2; + QButtonGroup* horizontalAlignButtons; + QButtonGroup* verticalAlignButtons; + QButtonGroup* positionButtons; void blockAlign(bool val); + void blockPosition(bool val); private slots: void _alignChanged(); + void _positionChanged(); }; } diff --git a/src/notation/view/widgets/align_select.ui b/src/notation/view/widgets/align_select.ui index 42b4483b20acd..ff3b519ebf63b 100644 --- a/src/notation/view/widgets/align_select.ui +++ b/src/notation/view/widgets/align_select.ui @@ -6,8 +6,8 @@ 0 0 - 200 - 32 + 300 + 64 @@ -33,6 +33,19 @@ 0 + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + @@ -48,7 +61,7 @@ - Align left edge of text to reference point + Left-align text within its bounding box true @@ -73,7 +86,7 @@ - Center text on reference point + Horizontally center text within its bounding box true @@ -98,7 +111,7 @@ - Align right edge of text to reference point + Right align text within its bounding box true @@ -108,7 +121,7 @@ - + @@ -133,15 +146,100 @@ + + + + + 28 + 28 + + + + + 28 + 28 + + + + Left-align text box to reference point + + + true + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Horizontally center text box to reference point + + + true + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Right-align text box to reference point + + + true + + + true + + + + + + + + + 0 + + + 4 + - Qt::Horizontal + Qt::Orientation::Horizontal - 0 - 0 + 40 + 20 @@ -246,6 +344,22 @@ + + + + Qt::Orientation::Horizontal + + + QSizePolicy::Policy::Fixed + + + + 84 + 20 + + + + diff --git a/src/notation/view/widgets/editstyle.cpp b/src/notation/view/widgets/editstyle.cpp index db64d5bae80d4..6965e7c0a4796 100644 --- a/src/notation/view/widgets/editstyle.cpp +++ b/src/notation/view/widgets/editstyle.cpp @@ -1051,6 +1051,7 @@ EditStyle::EditStyle(QWidget* parent) connect(buttonGroup, &QButtonGroup::buttonClicked, setSignalMapper, mapFunction); } else if (auto alignSelect = qobject_cast(sw.widget)) { connect(alignSelect, &AlignSelect::alignChanged, setSignalMapper, mapFunction); + connect(alignSelect, &AlignSelect::positionChanged, setSignalMapper, mapFunction); } else if (auto offsetSelect = qobject_cast(sw.widget)) { connect(offsetSelect, &OffsetSelect::offsetChanged, setSignalMapper, mapFunction); } else if (auto fontStyle = qobject_cast(sw.widget)) { @@ -1145,8 +1146,8 @@ EditStyle::EditStyle(QWidget* parent) textStyleValueChanged(TextStylePropertyType::TextAlign, textStyleAlign->align()); }); - connect(textPositionSelect, &TextPositionSelect::positionChanged, this, [=]() { - textStyleValueChanged(TextStylePropertyType::Position, textPositionSelect->position()); + connect(textStyleAlign, &AlignSelect::positionChanged, this, [=]() { + textStyleValueChanged(TextStylePropertyType::Position, textStyleAlign->position()); }); // offset @@ -1195,7 +1196,7 @@ EditStyle::EditStyle(QWidget* parent) connect(resetTextStyleFrameBorderRadius, &QToolButton::clicked, this, [=]() { resetTextStyle(TextStylePropertyType::FrameRound); }); - connect(textStyleFrameBorderRadius, &QDoubleSpinBox::valueChanged, this, [=]() { + connect(textStyleFrameBorderRadius, &QSpinBox::valueChanged, this, [=]() { textStyleValueChanged(TextStylePropertyType::FrameRound, textStyleFrameBorderRadius->value()); }); @@ -2762,7 +2763,7 @@ void EditStyle::textStyleChanged(int row) break; case TextStylePropertyType::Position: - textPositionSelect->setPosition(styleValue(a.sid).value()); + textStyleAlign->setPosition(styleValue(a.sid).value()); resetTextStyleAlign->setEnabled(styleValue(a.sid) != defaultStyleValue(a.sid)); break; diff --git a/src/notation/view/widgets/editstyle.ui b/src/notation/view/widgets/editstyle.ui index 91ca4dd4d22ff..96df008fc8080 100644 --- a/src/notation/view/widgets/editstyle.ui +++ b/src/notation/view/widgets/editstyle.ui @@ -7,7 +7,7 @@ 0 0 962 - 824 + 832 @@ -245,7 +245,7 @@ - 5 + 38 @@ -280,8 +280,8 @@ 0 0 - 408 - 517 + 652 + 710 @@ -924,8 +924,8 @@ 0 0 - 409 - 1110 + 641 + 1560 @@ -3227,8 +3227,8 @@ 0 0 - 664 - 592 + 716 + 731 @@ -4534,8 +4534,8 @@ 0 0 - 268 - 527 + 656 + 720 @@ -5337,8 +5337,8 @@ 0 0 - 401 - 583 + 641 + 787 @@ -6060,8 +6060,8 @@ 0 0 - 365 - 408 + 595 + 560 @@ -6948,8 +6948,8 @@ 0 0 - 459 - 494 + 656 + 720 @@ -10453,8 +10453,8 @@ 0 0 - 482 - 543 + 725 + 785 @@ -12042,8 +12042,8 @@ followed by dashes 0 0 - 362 - 543 + 650 + 708 @@ -12602,19 +12602,6 @@ followed by dashes Edit text style - - - - - - - Offset: - - - textStyleOffset - - - @@ -12628,67 +12615,20 @@ followed by dashes - - - - Style: - - - textStyleFontStyle - - - - - - - Size: - - - textStyleFontSize - - - - - - - - + + Reset to default - Reset 'Offset' values + Reset 'Font size' value - - - - Use musical symbols font for tuplet numbers - - - - - - - Follow staff size - - - - - - - Color: - - - textStyleColor - - - - + @@ -12764,16 +12704,6 @@ followed by dashes - - - - false - - - 0 - - - @@ -12896,12 +12826,141 @@ followed by dashes + + + + false + + + + + + + + + + + + + false + + + pt + + + 1.000000000000000 + + + + + + + false + + + li + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + Line spacing: + + + textStyleLineSpacing + + + + + + + Name: + + + styleName + + + + + + + Reset to default + + + Reset 'Offset' values + + + + + + + + + + + 0 + 0 + + + + + + + + Use musical symbols font for tuplet numbers + + + + + + + Font: + + + textStyleFontFace + + + + + + + Color: + + + textStyleColor + + + + + + + Offset: + + + textStyleOffset + + + + + + + Qt::FocusPolicy::StrongFocus + + + @@ -12945,156 +13004,114 @@ followed by dashes - - - - Reset to default + + + + + + + Align: - - Reset 'Font size' value + + textStyleAlign + + + + - + Follow staff size - - + + Reset to default - Reset 'Font face' value + Reset 'Font style' values - - + + Reset to default - Reset 'Align' values + Reset 'Follow staff size' value - - - - false - - - li - - - 0.100000000000000 - - - 1.000000000000000 - - - - - - - - 0 - 0 - - - - - - - - false - - - pt + + + + Style: - - 1.000000000000000 + + textStyleFontStyle - - + + Reset to default - Reset 'Color' value + Reset 'Font face' value - - + + + + + Reset to default - Reset 'Font style' values + Reset 'Color' value - - - - Qt::FocusPolicy::StrongFocus - - - - - - - Line spacing: - - - textStyleLineSpacing - - - - - + + Reset to default - Reset 'Follow staff size' value + Reset 'Name' value - - + + - Align: + Size: - textStyleAlign + textStyleFontSize - - - - - - @@ -13108,42 +13125,19 @@ followed by dashes - - - - Name: - - - styleName - - - - - - - Font: - - - textStyleFontFace - - - - - + + Reset to default - Reset 'Name' value + Reset 'Align' values - - - @@ -13205,6 +13199,12 @@ followed by dashes + + muse::uicomponents::RadioButtonGroupBox + QGroupBox +
uicomponents/view/widgets/radiobuttongroupbox.h
+ 1 +
Awl::ColorLabel QPushButton @@ -13229,18 +13229,6 @@ followed by dashes
notation/view/widgets/alignSelect.h
1
- - muse::uicomponents::RadioButtonGroupBox - QGroupBox -
uicomponents/view/widgets/radiobuttongroupbox.h
- 1 -
- - mu::notation::TextPositionSelect - QWidget -
notation/view/widgets/textpositionselect.h
- 1 -
pageList diff --git a/src/notation/view/widgets/text_position_select.ui b/src/notation/view/widgets/text_position_select.ui deleted file mode 100644 index 2d4db21f1f6ff..0000000000000 --- a/src/notation/view/widgets/text_position_select.ui +++ /dev/null @@ -1,132 +0,0 @@ - - - PositionSelect - - - - 0 - 0 - 94 - 32 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - 0 - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - - 28 - 28 - - - - - 28 - 28 - - - - Align left edge of text to reference point - - - true - - - true - - - - - - - - 28 - 28 - - - - - 28 - 28 - - - - Center text on reference point - - - true - - - true - - - - - - - - 28 - 28 - - - - - 28 - 28 - - - - Align right edge of text to reference point - - - true - - - true - - - - - - - - - - - - diff --git a/src/notation/view/widgets/textpositionselect.cpp b/src/notation/view/widgets/textpositionselect.cpp deleted file mode 100644 index 6ed9aacc89924..0000000000000 --- a/src/notation/view/widgets/textpositionselect.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-only - * MuseScore-Studio-CLA-applies - * - * MuseScore Studio - * Music Composition & Notation - * - * Copyright (C) 2025 MuseScore Limited - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "textpositionselect.h" - -#include - -#include "ui/view/widgetutils.h" - -using namespace mu::notation; -using namespace muse::ui; - -TextPositionSelect::TextPositionSelect(QWidget* parent) - : QWidget(parent), muse::Injectable(muse::iocCtxForQWidget(this)) -{ - setupUi(this); - - positionButtons = new QButtonGroup(this); - positionButtons->addButton(positionLeft); - positionButtons->addButton(positionHCenter); - positionButtons->addButton(positionRight); - - WidgetUtils::setWidgetIcon(positionLeft, IconCode::Code::ALIGN_LEFT); - WidgetUtils::setWidgetIcon(positionRight, IconCode::Code::ALIGN_RIGHT); - WidgetUtils::setWidgetIcon(positionHCenter, IconCode::Code::ALIGN_HORIZONTAL_CENTER); - - connect(positionButtons, &QButtonGroup::buttonToggled, this, &TextPositionSelect::_positionChanged); - connect(positionButtons, &QButtonGroup::buttonToggled, this, &TextPositionSelect::_positionChanged); -} - -void TextPositionSelect::_positionChanged() -{ - emit positionChanged(position()); -} - -mu::engraving::AlignH TextPositionSelect::position() const -{ - mu::engraving::AlignH position = mu::engraving::AlignH::LEFT; - if (positionHCenter->isChecked()) { - position = mu::engraving::AlignH::HCENTER; - } else if (positionRight->isChecked()) { - position = mu::engraving::AlignH::RIGHT; - } - return position; -} - -void TextPositionSelect::setPosition(mu::engraving::AlignH a) -{ - blockPosition(true); - if (a == mu::engraving::AlignH::HCENTER) { - positionHCenter->setChecked(true); - } else if (a == mu::engraving::AlignH::RIGHT) { - positionRight->setChecked(true); - } else { - positionLeft->setChecked(true); - } - blockPosition(false); -} - -void TextPositionSelect::blockPosition(bool val) -{ - positionButtons->blockSignals(val); -} diff --git a/src/notation/view/widgets/textpositionselect.h b/src/notation/view/widgets/textpositionselect.h deleted file mode 100644 index 3bdda915db8f9..0000000000000 --- a/src/notation/view/widgets/textpositionselect.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0-only - * MuseScore-Studio-CLA-applies - * - * MuseScore Studio - * Music Composition & Notation - * - * Copyright (C) 2025 MuseScore Limited - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include "modularity/ioc.h" -#include "ui_text_position_select.h" -#include "engraving/types/types.h" - -namespace mu::notation { -class TextPositionSelect : public QWidget, public Ui::PositionSelect, public muse::Injectable -{ - Q_OBJECT - -public: - TextPositionSelect(QWidget* parent); - mu::engraving::AlignH position() const; - void setPosition(mu::engraving::AlignH); - -signals: - void positionChanged(mu::engraving::AlignH); - -private: - QButtonGroup* positionButtons; - - void blockPosition(bool val); - -private slots: - void _positionChanged(); -}; -} diff --git a/src/notation/view/widgets/widgets.cmake b/src/notation/view/widgets/widgets.cmake index 64ac35516eec5..044afd797c513 100644 --- a/src/notation/view/widgets/widgets.cmake +++ b/src/notation/view/widgets/widgets.cmake @@ -43,6 +43,4 @@ set(WIDGETS_SRC ${CMAKE_CURRENT_LIST_DIR}/timeline.h ${CMAKE_CURRENT_LIST_DIR}/realizeharmonydialog.cpp ${CMAKE_CURRENT_LIST_DIR}/realizeharmonydialog.h - ${CMAKE_CURRENT_LIST_DIR}/textpositionselect.cpp - ${CMAKE_CURRENT_LIST_DIR}/textpositionselect.h ) diff --git a/vtest/scores/text-align.mscz b/vtest/scores/text-align.mscz new file mode 100644 index 0000000000000..43f3cb7bceccf Binary files /dev/null and b/vtest/scores/text-align.mscz differ