From 65f56d02eeb711558c2d4de52d9fcfb28f0e04ef Mon Sep 17 00:00:00 2001 From: Eism Date: Wed, 2 Feb 2022 16:58:56 +0200 Subject: [PATCH] Sending appropriate text change signals instead of a single cursor change signal --- .../accessibility/accessibleitem.cpp | 4 +- src/engraving/accessibility/accessibleitem.h | 6 +-- src/engraving/libmscore/textbase.cpp | 19 ++++++++ src/engraving/libmscore/textbase.h | 4 ++ src/engraving/libmscore/textedit.cpp | 47 ++++++++++++++++++- src/framework/accessibility/iaccessible.h | 36 ++++++++++++-- .../internal/accessibilitycontroller.cpp | 30 ++++++++---- .../internal/accessibilitycontroller.h | 6 +-- .../internal/accessibleiteminterface.cpp | 2 +- .../tests/accessibilitycontroller_tests.cpp | 6 +-- src/framework/ui/view/qmlaccessible.cpp | 12 ++--- src/framework/ui/view/qmlaccessible.h | 6 +-- src/notation/internal/notationinteraction.cpp | 16 ------- 13 files changed, 144 insertions(+), 50 deletions(-) diff --git a/src/engraving/accessibility/accessibleitem.cpp b/src/engraving/accessibility/accessibleitem.cpp index 9f4e41987e..1966b4bcf1 100644 --- a/src/engraving/accessibility/accessibleitem.cpp +++ b/src/engraving/accessibility/accessibleitem.cpp @@ -295,7 +295,7 @@ QString AccessibleItem::accessibleTextAtOffset(int offset, TextBoundaryType boun return result; } -int AccessibleItem::accesibleCharacterCount() const +int AccessibleItem::accessibleCharacterCount() const { if (!m_element || !m_element->isTextBase()) { return 0; @@ -338,7 +338,7 @@ QRect AccessibleItem::accessibleRect() const return rect; } -mu::async::Channel AccessibleItem::accessiblePropertyChanged() const +mu::async::Channel AccessibleItem::accessiblePropertyChanged() const { return m_accessiblePropertyChanged; } diff --git a/src/engraving/accessibility/accessibleitem.h b/src/engraving/accessibility/accessibleitem.h index d2de70b7e8..00faf5305e 100644 --- a/src/engraving/accessibility/accessibleitem.h +++ b/src/engraving/accessibility/accessibleitem.h @@ -75,9 +75,9 @@ public: QString accessibleText(int startOffset, int endOffset) const override; QString accessibleTextAtOffset(int offset, TextBoundaryType boundaryType, int* startOffset, int* endOffset) const override; - int accesibleCharacterCount() const override; + int accessibleCharacterCount() const override; - async::Channel accessiblePropertyChanged() const override; + async::Channel accessiblePropertyChanged() const override; async::Channel accessibleStateChanged() const override; // --- @@ -93,7 +93,7 @@ protected: Role m_role = Role::ElementOnScore; - mu::async::Channel m_accessiblePropertyChanged; + mu::async::Channel m_accessiblePropertyChanged; mu::async::Channel m_accessibleStateChanged; }; } diff --git a/src/engraving/libmscore/textbase.cpp b/src/engraving/libmscore/textbase.cpp index 3092f86847..5a022926ea 100644 --- a/src/engraving/libmscore/textbase.cpp +++ b/src/engraving/libmscore/textbase.cpp @@ -3064,6 +3064,25 @@ AccessibleItem* TextBase::createAccessible() return new AccessibleItem(this, AccessibleItem::EditableText); } +void TextBase::notifyAboutTextCursorChanged() +{ + accessible()->accessiblePropertyChanged().send(accessibility::IAccessible::Property::TextCursor, Val()); +} + +void TextBase::notifyAboutTextInserted(int startPosition, int endPosition, const QString& text) +{ + auto range = accessibility::IAccessible::TextRange(startPosition, endPosition, text); + accessible()->accessiblePropertyChanged().send(accessibility::IAccessible::Property::TextInsert, + Val(range.toMap())); +} + +void TextBase::notifyAboutTextRemoved(int startPosition, int endPosition, const QString& text) +{ + auto range = accessibility::IAccessible::TextRange(startPosition, endPosition, text); + accessible()->accessiblePropertyChanged().send(accessibility::IAccessible::Property::TextRemove, + Val(range.toMap())); +} + //--------------------------------------------------------- // getPropertyStyle //--------------------------------------------------------- diff --git a/src/engraving/libmscore/textbase.h b/src/engraving/libmscore/textbase.h index 7821e8803c..e440cb93df 100644 --- a/src/engraving/libmscore/textbase.h +++ b/src/engraving/libmscore/textbase.h @@ -313,6 +313,10 @@ class TextBase : public EngravingItem mu::engraving::AccessibleItem* createAccessible() override; + void notifyAboutTextCursorChanged(); + void notifyAboutTextInserted(int startPosition, int endPosition, const QString& text); + void notifyAboutTextRemoved(int startPosition, int endPosition, const QString& text); + protected: TextBase(const ElementType& type, EngravingItem* parent = 0, TextStyleType tid = TextStyleType::DEFAULT, ElementFlags = ElementFlag::NOTHING); diff --git a/src/engraving/libmscore/textedit.cpp b/src/engraving/libmscore/textedit.cpp index 9866ccd4d2..253464c4ce 100644 --- a/src/engraving/libmscore/textedit.cpp +++ b/src/engraving/libmscore/textedit.cpp @@ -27,6 +27,8 @@ #include "scorefont.h" #include "types/symnames.h" +#include "accessibility/accessibleitem.h" + #include "log.h" using namespace mu; @@ -310,6 +312,9 @@ bool TextBase::edit(EditData& ed) case Qt::Key_Return: deleteSelectedText(ed); score()->undo(new SplitText(cursor), &ed); + + notifyAboutTextCursorChanged(); + return true; case Qt::Key_Delete: @@ -325,16 +330,28 @@ bool TextBase::edit(EditData& ed) } else { score()->undo(new RemoveText(cursor, QString(cursor->currentCharacter())), &ed); } + +// notifyAboutTextRemoved() // todo } return true; - case Qt::Key_Backspace: + case Qt::Key_Backspace: { + int startPosition = cursor->currentPosition(); + if (ctrlPressed) { // delete last word cursor->movePosition(TextCursor::MoveOperation::WordLeft, TextCursor::MoveMode::KeepAnchor); + int endPosition = cursor->currentPosition(); + QString text = cursor->selectedText(); + s.clear(); - deleteSelectedText(ed); + + if (deleteSelectedText(ed)) { + notifyAboutTextRemoved(startPosition, endPosition, text); + } } else { + QString text = cursor->selectedText(); + if (!deleteSelectedText(ed)) { if (cursor->column() == 0 && _cursor->row() != 0) { score()->undo(new JoinText(cursor), &ed); @@ -344,9 +361,12 @@ bool TextBase::edit(EditData& ed) } score()->undo(new RemoveText(cursor, QString(cursor->currentCharacter())), &ed); } + } else { + notifyAboutTextRemoved(startPosition, startPosition - 1, text); } } return true; + } case Qt::Key_Left: if (!_cursor->movePosition(ctrlPressed ? TextCursor::MoveOperation::WordLeft : TextCursor::MoveOperation::Left, @@ -354,6 +374,9 @@ bool TextBase::edit(EditData& ed) return false; } s.clear(); + + notifyAboutTextCursorChanged(); + break; case Qt::Key_Right: @@ -362,6 +385,9 @@ bool TextBase::edit(EditData& ed) return false; } s.clear(); + + notifyAboutTextCursorChanged(); + break; case Qt::Key_Up: @@ -373,6 +399,9 @@ bool TextBase::edit(EditData& ed) cursor->movePosition(TextCursor::MoveOperation::Up, mm); #endif s.clear(); + + notifyAboutTextCursorChanged(); + break; case Qt::Key_Down: @@ -384,6 +413,9 @@ bool TextBase::edit(EditData& ed) cursor->movePosition(TextCursor::MoveOperation::Down, mm); #endif s.clear(); + + notifyAboutTextCursorChanged(); + break; case Qt::Key_Home: @@ -394,6 +426,9 @@ bool TextBase::edit(EditData& ed) } s.clear(); + + notifyAboutTextCursorChanged(); + break; case Qt::Key_End: @@ -404,6 +439,9 @@ bool TextBase::edit(EditData& ed) } s.clear(); + + notifyAboutTextCursorChanged(); + break; case Qt::Key_Tab: @@ -442,6 +480,8 @@ bool TextBase::edit(EditData& ed) cursor->movePosition(TextCursor::MoveOperation::Start, TextCursor::MoveMode::MoveAnchor); cursor->movePosition(TextCursor::MoveOperation::End, TextCursor::MoveMode::KeepAnchor); s.clear(); + + notifyAboutTextCursorChanged(); } break; case Qt::Key_B: @@ -519,6 +559,9 @@ bool TextBase::edit(EditData& ed) if (!s.isEmpty()) { deleteSelectedText(ed); score()->undo(new InsertText(_cursor, s), &ed); + + int startPosition = cursor->currentPosition(); + notifyAboutTextInserted(startPosition, startPosition + s.size(), s); } return true; } diff --git a/src/framework/accessibility/iaccessible.h b/src/framework/accessibility/iaccessible.h index 1c01d9dcd8..dc4c4f62b7 100644 --- a/src/framework/accessibility/iaccessible.h +++ b/src/framework/accessibility/iaccessible.h @@ -23,10 +23,14 @@ #define MU_ACCESSIBILITY_IACCESSIBLE_H #include + #include #include #include +#include + #include "async/channel.h" +#include "val.h" class QWindow; @@ -75,7 +79,9 @@ public: Name, Description, Value, - Selection + TextCursor, + TextInsert, + TextRemove }; enum TextBoundaryType { @@ -87,6 +93,30 @@ public: NoBoundary }; + struct TextRange { + int startPosition = 0; + int endPosition = 0; + QString text; + + TextRange(int startPosition, int endPosition, const QString& text) + : startPosition(startPosition), endPosition(endPosition), text(text) {} + TextRange(const QVariantMap& map) + { + startPosition = map.value("startPosition").toInt(); + endPosition = map.value("endPosition").toInt(); + text = map.value("startPosition").toString(); + } + + QVariantMap toMap() const + { + return { + { "startPosition", startPosition }, + { "endPosition", endPosition }, + { "text", text } + }; + } + }; + virtual const IAccessible* accessibleParent() const = 0; virtual size_t accessibleChildCount() const = 0; virtual const IAccessible* accessibleChild(size_t i) const = 0; @@ -111,9 +141,9 @@ public: virtual QString accessibleText(int startOffset, int endOffset) const = 0; virtual QString accessibleTextAtOffset(int offset, TextBoundaryType boundaryType, int* startOffset, int* endOffset) const = 0; - virtual int accesibleCharacterCount() const = 0; + virtual int accessibleCharacterCount() const = 0; - virtual async::Channel accessiblePropertyChanged() const = 0; + virtual async::Channel accessiblePropertyChanged() const = 0; virtual async::Channel accessibleStateChanged() const = 0; }; } diff --git a/src/framework/accessibility/internal/accessibilitycontroller.cpp b/src/framework/accessibility/internal/accessibilitycontroller.cpp index 5a36d5223f..faa2b9c490 100644 --- a/src/framework/accessibility/internal/accessibilitycontroller.cpp +++ b/src/framework/accessibility/internal/accessibilitycontroller.cpp @@ -110,8 +110,8 @@ void AccessibilityController::reg(IAccessible* item) m_children.append(item); } - item->accessiblePropertyChanged().onReceive(this, [this, item](const IAccessible::Property& p) { - propertyChanged(item, p); + item->accessiblePropertyChanged().onReceive(this, [this, item](const IAccessible::Property& p, const Val value) { + propertyChanged(item, p, value); }); item->accessibleStateChanged().onReceive(this, [this, item](const State& state, bool arg) { @@ -155,7 +155,7 @@ const IAccessible* AccessibilityController::lastFocused() const return m_lastFocused; } -void AccessibilityController::propertyChanged(IAccessible* item, IAccessible::Property p) +void AccessibilityController::propertyChanged(IAccessible* item, IAccessible::Property property, const Val& value) { const Item& it = findItem(item); if (!it.isValid()) { @@ -163,7 +163,7 @@ void AccessibilityController::propertyChanged(IAccessible* item, IAccessible::Pr } QAccessible::Event etype = QAccessible::InvalidEvent; - switch (p) { + switch (property) { case IAccessible::Property::Undefined: return; case IAccessible::Property::Parent: etype = QAccessible::ParentChanged; @@ -177,11 +177,25 @@ void AccessibilityController::propertyChanged(IAccessible* item, IAccessible::Pr sendEvent(&ev); return; } - case IAccessible::Property::Selection: { + case IAccessible::Property::TextCursor: { QAccessibleTextCursorEvent ev(it.object, it.item->accessibleCursorPosition()); sendEvent(&ev); return; } + case IAccessible::Property::TextInsert: { + IAccessible::TextRange range(value.toQVariant().toMap()); + QAccessibleTextInsertEvent ev(it.object, range.startPosition, + it.item->accessibleText(range.startPosition, range.endPosition)); + sendEvent(&ev); + return; + } + case IAccessible::Property::TextRemove: { + IAccessible::TextRange range(value.toQVariant().toMap()); + QAccessibleTextRemoveEvent ev(it.object, range.startPosition, + it.item->accessibleText(range.startPosition, range.endPosition)); + sendEvent(&ev); + return; + } } QAccessibleEvent ev(it.object, etype); @@ -477,14 +491,14 @@ QString AccessibilityController::accessibleTextAtOffset(int, TextBoundaryType, i return QString(); } -int AccessibilityController::accesibleCharacterCount() const +int AccessibilityController::accessibleCharacterCount() const { return 0; } -mu::async::Channel AccessibilityController::accessiblePropertyChanged() const +mu::async::Channel AccessibilityController::accessiblePropertyChanged() const { - static async::Channel ch; + static async::Channel ch; return ch; } diff --git a/src/framework/accessibility/internal/accessibilitycontroller.h b/src/framework/accessibility/internal/accessibilitycontroller.h index 1c16d50e20..3c604f5495 100644 --- a/src/framework/accessibility/internal/accessibilitycontroller.h +++ b/src/framework/accessibility/internal/accessibilitycontroller.h @@ -94,9 +94,9 @@ public: QString accessibleText(int startOffset, int endOffset) const override; QString accessibleTextAtOffset(int offset, TextBoundaryType boundaryType, int* startOffset, int* endOffset) const override; - int accesibleCharacterCount() const override; + int accessibleCharacterCount() const override; - async::Channel accessiblePropertyChanged() const override; + async::Channel accessiblePropertyChanged() const override; async::Channel accessibleStateChanged() const override; // ----- @@ -125,7 +125,7 @@ private: const Item& findItem(const IAccessible* aitem) const; - void propertyChanged(IAccessible* item, IAccessible::Property p); + void propertyChanged(IAccessible* item, IAccessible::Property property, const Val& value); void stateChanged(IAccessible* item, IAccessible::State state, bool arg); void sendEvent(QAccessibleEvent* ev); diff --git a/src/framework/accessibility/internal/accessibleiteminterface.cpp b/src/framework/accessibility/internal/accessibleiteminterface.cpp index e17e03de9c..1361409bef 100644 --- a/src/framework/accessibility/internal/accessibleiteminterface.cpp +++ b/src/framework/accessibility/internal/accessibleiteminterface.cpp @@ -334,7 +334,7 @@ QString AccessibleItemInterface::textAtOffset(int offset, QAccessible::TextBound int AccessibleItemInterface::characterCount() const { - return m_object->item()->accesibleCharacterCount(); + return m_object->item()->accessibleCharacterCount(); } QRect AccessibleItemInterface::characterRect(int) const diff --git a/src/framework/accessibility/tests/accessibilitycontroller_tests.cpp b/src/framework/accessibility/tests/accessibilitycontroller_tests.cpp index 57292bcc14..c4eb289749 100644 --- a/src/framework/accessibility/tests/accessibilitycontroller_tests.cpp +++ b/src/framework/accessibility/tests/accessibilitycontroller_tests.cpp @@ -82,9 +82,9 @@ public: QString accessibleText(int, int) const override { return QString(); } QString accessibleTextAtOffset(int, TextBoundaryType, int*, int*) const override { return QString(); } - int accesibleCharacterCount() const override { return 0; } + int accessibleCharacterCount() const override { return 0; } - async::Channel accessiblePropertyChanged() const override + async::Channel accessiblePropertyChanged() const override { return m_propertyChanged; } @@ -94,7 +94,7 @@ public: return m_stateChanged; } - async::Channel m_propertyChanged; + async::Channel m_propertyChanged; async::Channel m_stateChanged; AccessibleItem* m_parent = nullptr; diff --git a/src/framework/ui/view/qmlaccessible.cpp b/src/framework/ui/view/qmlaccessible.cpp index 275d051be9..101a64338e 100644 --- a/src/framework/ui/view/qmlaccessible.cpp +++ b/src/framework/ui/view/qmlaccessible.cpp @@ -189,12 +189,12 @@ QString AccessibleItem::accessibleTextAtOffset(int, TextBoundaryType, int*, int* return QString(); } -int AccessibleItem::accesibleCharacterCount() const +int AccessibleItem::accessibleCharacterCount() const { return 0; } -mu::async::Channel AccessibleItem::accessiblePropertyChanged() const +mu::async::Channel AccessibleItem::accessiblePropertyChanged() const { return m_accessiblePropertyChanged; } @@ -226,7 +226,7 @@ void AccessibleItem::setAccessibleParent(AccessibleItem* p) } emit accessiblePrnChanged(); - m_accessiblePropertyChanged.send(IAccessible::Property::Parent); + m_accessiblePropertyChanged.send(IAccessible::Property::Parent, Val()); } void AccessibleItem::setState(IAccessible::State st, bool arg) @@ -268,7 +268,7 @@ void AccessibleItem::setName(QString name) m_name = name; emit nameChanged(m_name); - m_accessiblePropertyChanged.send(IAccessible::Property::Name); + m_accessiblePropertyChanged.send(IAccessible::Property::Name, Val(name)); } void AccessibleItem::setDescription(QString description) @@ -279,7 +279,7 @@ void AccessibleItem::setDescription(QString description) m_description = description; emit descriptionChanged(m_description); - m_accessiblePropertyChanged.send(IAccessible::Property::Description); + m_accessiblePropertyChanged.send(IAccessible::Property::Description, Val(description)); } void AccessibleItem::setValue(QVariant value) @@ -290,7 +290,7 @@ void AccessibleItem::setValue(QVariant value) m_value = value; emit valueChanged(m_value); - m_accessiblePropertyChanged.send(IAccessible::Property::Value); + m_accessiblePropertyChanged.send(IAccessible::Property::Value, Val(value)); } void AccessibleItem::setMaximumValue(QVariant maximumValue) diff --git a/src/framework/ui/view/qmlaccessible.h b/src/framework/ui/view/qmlaccessible.h index aa5d4e313c..2086c17726 100644 --- a/src/framework/ui/view/qmlaccessible.h +++ b/src/framework/ui/view/qmlaccessible.h @@ -135,9 +135,9 @@ public: QString accessibleText(int startOffset, int endOffset) const override; QString accessibleTextAtOffset(int offset, TextBoundaryType boundaryType, int* startOffset, int* endOffset) const override; - int accesibleCharacterCount() const override; + int accessibleCharacterCount() const override; - async::Channel accessiblePropertyChanged() const override; + async::Channel accessiblePropertyChanged() const override; async::Channel accessibleStateChanged() const override; // ----- @@ -186,7 +186,7 @@ private: bool m_ignored = false; QQuickItem* m_visualItem = nullptr; QMap m_state; - async::Channel m_accessiblePropertyChanged; + async::Channel m_accessiblePropertyChanged; async::Channel m_accessibleStateChanged; }; } diff --git a/src/notation/internal/notationinteraction.cpp b/src/notation/internal/notationinteraction.cpp index 06d394d4cd..7e1c2eccc0 100644 --- a/src/notation/internal/notationinteraction.cpp +++ b/src/notation/internal/notationinteraction.cpp @@ -178,19 +178,6 @@ void NotationInteraction::notifyAboutTextEditingChanged() m_textEditingChanged.notify(); } -void NotationInteraction::notifyAboutTextCursorChanged() -{ - if (!m_editData.element || !m_editData.element->isTextBase()) { - return; - } - - Ms::TextBase* text = toTextBase(m_editData.element); - auto accessibleItem = text->accessible(); - if (accessibleItem) { - accessibleItem->accessiblePropertyChanged().send(AccessibleItem::Property::Selection); - } -} - void NotationInteraction::notifyAboutSelectionChanged() { updateGripEdit(); @@ -2473,7 +2460,6 @@ void NotationInteraction::editText(QInputMethodEvent* event) event->accept(); notifyAboutTextEditingChanged(); - notifyAboutTextCursorChanged(); } static qreal nudgeDistance(const Ms::EditData& editData) @@ -2600,7 +2586,6 @@ void NotationInteraction::changeTextCursorPosition(const PointF& newCursorPos) } notifyAboutTextEditingChanged(); - notifyAboutTextCursorChanged(); } const TextBase* NotationInteraction::editedText() const @@ -2775,7 +2760,6 @@ void NotationInteraction::editElement(QKeyEvent* event) } if (isTextEditingStarted()) { notifyAboutTextEditingChanged(); - notifyAboutTextCursorChanged(); } else { if (bracketIndex >= 0 && systemIndex < score()->systems().size()) { Ms::System* sys = score()->systems()[systemIndex];