Skip to content

transform notation actions to commands#34150

Merged
igorkorsukov merged 1 commit into
musescore:mainfrom
igorkorsukov:w/rcmd/rcmd_step11
Jul 10, 2026
Merged

transform notation actions to commands#34150
igorkorsukov merged 1 commit into
musescore:mainfrom
igorkorsukov:w/rcmd/rcmd_step11

Conversation

@igorkorsukov

Copy link
Copy Markdown
Member

No description provided.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds articulation, voice-selection, and flip commands, along with controller queries for rest, articulation, and voice state. Command registration and state evaluation now use these queries to update availability. Note input UI configuration references the new command identifiers, while NoteInputBarModel delegates input permission to the commands controller and removes its former notation and selection state management.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is missing entirely, so it does not satisfy the required template sections. Add the required template sections: issue reference, short motivation, and the checklist items for CLA, title, commits, testing, unnecessary changes, and tests.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: notation actions were transformed into commands.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Linked repositories: Public OSS repositories can only analyze public repositories installed in this organization. No linked repositories were analyzed; skipped musescore/muse_framework.git.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/notationscene/internal/notationcommandsstate.cpp (1)

273-279: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer removing commented-out logging over keeping it.

Consider dropping the commented LOGDA() block rather than leaving it as dead code; if per-command tracing is still useful, guarding it behind a trace level would be cleaner.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/notationscene/internal/notationcommandsstate.cpp` around lines 273 - 279,
Remove the commented-out LOGDA() block from NotationCommandsState::commandState;
leave the method returning the result of doCommandState(command), or implement
active trace-level logging if per-command diagnostics are still required.
src/notationscene/internal/notationactioncontroller.cpp (1)

1110-1112: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Prefer std::set member lookup over std::find.

std::find performs a linear O(n) scan on currentNoteArticulations. Using the set's member count() or find() would be O(log n). Impact is negligible for small articulation sets, but it's the idiomatic approach for ordered associative containers.

♻️ Proposed refactor
             for (auto it = result.begin(); it != result.end();) {
-                if (std::find(currentNoteArticulations.begin(), currentNoteArticulations.end(),
-                              *it) == currentNoteArticulations.end()) {
+                if (currentNoteArticulations.count(*it) == 0) {
                     it = result.erase(it);
                 } else {
                     ++it;
                 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/notationscene/internal/notationactioncontroller.cpp` around lines 1110 -
1112, Replace the linear std::find check in the result iteration within the
notation action controller with currentNoteArticulations.count(*it) or
currentNoteArticulations.find(*it), preserving the existing condition and
behavior while using the set’s logarithmic member lookup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/notationscene/internal/notationactioncontroller.cpp`:
- Around line 1018-1050: currentIsRest() incorrectly returns true for an empty
non-range selection. After obtaining the selection elements in currentIsRest(),
add an early return false when the collection is empty, before iterating and
checking isRest(), matching the guard used by currentVoice().

In `@src/notationscene/internal/notationcommandsstate.cpp`:
- Around line 146-151: Add ADD_ARTICULATION_COMMANDS to the selectionChanged()
notification handler alongside the existing updateCommandStates calls, so
articulation command states refresh whenever the selection changes.

---

Nitpick comments:
In `@src/notationscene/internal/notationactioncontroller.cpp`:
- Around line 1110-1112: Replace the linear std::find check in the result
iteration within the notation action controller with
currentNoteArticulations.count(*it) or currentNoteArticulations.find(*it),
preserving the existing condition and behavior while using the set’s logarithmic
member lookup.

In `@src/notationscene/internal/notationcommandsstate.cpp`:
- Around line 273-279: Remove the commented-out LOGDA() block from
NotationCommandsState::commandState; leave the method returning the result of
doCommandState(command), or implement active trace-level logging if per-command
diagnostics are still required.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9af83cc4-7030-41e0-abeb-84f8922e8d9d

📥 Commits

Reviewing files that changed from the base of the PR and between f63b3d1 and 06050d1.

📒 Files selected for processing (10)
  • src/notationscene/inotationcommandscontroller.h
  • src/notationscene/internal/notationactioncontroller.cpp
  • src/notationscene/internal/notationactioncontroller.h
  • src/notationscene/internal/notationcommandsregister.cpp
  • src/notationscene/internal/notationcommandsstate.cpp
  • src/notationscene/internal/notationuiactions.cpp
  • src/notationscene/internal/notationuiactions.h
  • src/notationscene/notationcommands.h
  • src/notationscene/qml/MuseScore/NotationScene/noteinputbarmodel.cpp
  • src/notationscene/qml/MuseScore/NotationScene/noteinputbarmodel.h
💤 Files with no reviewable changes (1)
  • src/notationscene/internal/notationuiactions.h

Comment on lines +1018 to +1050
bool NotationActionController::currentIsRest() const
{
INotationInteractionPtr interaction = currentNotationInteraction();
if (!interaction) {
return false;
}

INotationNoteInputPtr noteInput = interaction->noteInput();
if (!noteInput) {
return false;
}

if (noteInput->isNoteInputMode()) {
return noteInput->state().rest();
}

INotationSelectionPtr selection = interaction->selection();
if (!selection) {
return false;
}

if (selection->isNone() || selection->isRange()) {
return false;
}

for (const EngravingItem* element: selection->elements()) {
if (!element->isRest()) {
return false;
}
}

return true;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Guard against empty selection in currentIsRest().

If selection->isNone() is false and selection->isRange() is false but selection->elements() is empty, the loop body never executes and the function returns true (vacuous truth). currentVoice() at Line 1152 explicitly guards this case with selectedElements.empty(), but currentIsRest() does not. Add an early return for consistency and correctness.

🛡️ Proposed fix
     if (selection->isNone() || selection->isRange()) {
         return false;
     }

+    if (selection->elements().empty()) {
+        return false;
+    }
+
     for (const EngravingItem* element: selection->elements()) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bool NotationActionController::currentIsRest() const
{
INotationInteractionPtr interaction = currentNotationInteraction();
if (!interaction) {
return false;
}
INotationNoteInputPtr noteInput = interaction->noteInput();
if (!noteInput) {
return false;
}
if (noteInput->isNoteInputMode()) {
return noteInput->state().rest();
}
INotationSelectionPtr selection = interaction->selection();
if (!selection) {
return false;
}
if (selection->isNone() || selection->isRange()) {
return false;
}
for (const EngravingItem* element: selection->elements()) {
if (!element->isRest()) {
return false;
}
}
return true;
}
bool NotationActionController::currentIsRest() const
{
INotationInteractionPtr interaction = currentNotationInteraction();
if (!interaction) {
return false;
}
INotationNoteInputPtr noteInput = interaction->noteInput();
if (!noteInput) {
return false;
}
if (noteInput->isNoteInputMode()) {
return noteInput->state().rest();
}
INotationSelectionPtr selection = interaction->selection();
if (!selection) {
return false;
}
if (selection->isNone() || selection->isRange()) {
return false;
}
if (selection->elements().empty()) {
return false;
}
for (const EngravingItem* element: selection->elements()) {
if (!element->isRest()) {
return false;
}
}
return true;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/notationscene/internal/notationactioncontroller.cpp` around lines 1018 -
1050, currentIsRest() incorrectly returns true for an empty non-range selection.
After obtaining the selection elements in currentIsRest(), add an early return
false when the collection is empty, before iterating and checking isRest(),
matching the guard used by currentVoice().

Comment on lines 146 to 151
controller()->selectionChanged().onNotify(this, [this]() {
updateCommandStates(HAS_SELECTION_REQUIRED_COMMANDS);
updateCommandStates(ADD_COMMANDS);
updateCommandStates({ PAD_REST_COMMAND });
updateCommandStates(commands(VOICE_COMMANDS));
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant file around the reported lines
sed -n '1,340p' src/notationscene/internal/notationcommandsstate.cpp

printf '\n--- SEARCH: ADD_ARTICULATION_COMMANDS ---\n'
rg -n "ADD_ARTICULATION_COMMANDS|HAS_SELECTION_REQUIRED_COMMANDS|PAD_REST_COMMAND|VOICE_COMMANDS|currentArticulations|selectionChanged\(|noteInputStateChanged\(" src/notationscene/internal/notationcommandsstate.cpp src -g'*.cpp' -g'*.h'

Repository: musescore/MuseScore

Length of output: 20531


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect articulation source and selection-change flow in the controller
sed -n '1020,1095p' src/notationscene/internal/notationactioncontroller.cpp
printf '\n---\n'
sed -n '1160,1205p' src/notationscene/internal/notationactioncontroller.cpp
printf '\n---\n'
sed -n '1948,2005p' src/notationscene/internal/notationactioncontroller.cpp

printf '\n--- SEARCH: articulation notifications/usages ---\n'
rg -n "currentArticulations\(|articulation|selectionChanged\(\)\.notify|selectionChanged\(\).onNotify|noteInputStateChanged\(\)\.notify" src/notationscene/internal/notationactioncontroller.cpp src/notationscene/internal/notationcommandsstate.cpp src/notationscene -g'*.cpp' -g'*.h'

Repository: musescore/MuseScore

Length of output: 11563


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the controller's selection-change notification path around the line reported by search
sed -n '520,590p' src/notationscene/internal/notationactioncontroller.cpp

printf '\n---\n'
sed -n '1295,1355p' src/notationscene/internal/notationactioncontroller.cpp

printf '\n---\n'
sed -n '1,140p' src/notationscene/internal/notationactioncontroller.h

Repository: musescore/MuseScore

Length of output: 11273


Refresh articulation command state on selection changes. selectionChanged() updates voice/rest, but not ADD_ARTICULATION_COMMANDS, so marcato/sforzato/tenuto/staccato can stay stale after a plain selection change. Add the articulation commands here too.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/notationscene/internal/notationcommandsstate.cpp` around lines 146 - 151,
Add ADD_ARTICULATION_COMMANDS to the selectionChanged() notification handler
alongside the existing updateCommandStates calls, so articulation command states
refresh whenever the selection changes.

@igorkorsukov igorkorsukov merged commit 83bc55b into musescore:main Jul 10, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants