Skip to content

feat: add select all notes in chord action#33762

Open
JohannJEG wants to merge 2 commits into
musescore:mainfrom
JohannJEG:feature/select-all-chord-notes
Open

feat: add select all notes in chord action#33762
JohannJEG wants to merge 2 commits into
musescore:mainfrom
JohannJEG:feature/select-all-chord-notes

Conversation

@JohannJEG

Copy link
Copy Markdown
Contributor

Resolves: #33670

Summary

Implements a new action to expand the current note selection to all notes within their chord(s).

When one or more notes are selected:

  • All notes in their respective chords are selected
  • If multiple notes across different chords are selected, all chords are expanded
  • The resulting selection replaces the current selection

Shortcut

  • Windows/Linux: Ctrl + Alt + A
  • Mac: Cmd + Opt + A

@JohannJEG JohannJEG force-pushed the feature/select-all-chord-notes branch from 5984409 to bd26e5f Compare June 10, 2026 00:21
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 43a29cb5-0768-4f50-af04-9c291faa80c5

📥 Commits

Reviewing files that changed from the base of the PR and between bd26e5f and 1cdc981.

📒 Files selected for processing (6)
  • src/app/configs/data/shortcuts.xml
  • src/app/configs/data/shortcuts_azerty.xml
  • src/app/configs/data/shortcuts_mac.xml
  • src/notationscene/internal/notationactioncontroller.cpp
  • src/notationscene/internal/notationactioncontroller.h
  • src/notationscene/internal/notationuiactions.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/app/configs/data/shortcuts_azerty.xml
  • src/app/configs/data/shortcuts_mac.xml
  • src/notationscene/internal/notationactioncontroller.h

📝 Walkthrough

Walkthrough

This PR adds a new notation UI action "select-notes-in-chord" and its labels, declares and implements NotationActionController::selectAllNotesInChord() which finds chords referenced by selected note elements and selects all notes from those chords, registers the action handler gated on an active selection, and binds the action to Ctrl+Alt+A in standard, AZERTY, and Mac shortcut config files.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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 (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: add select all notes in chord action' clearly and concisely describes the main feature being added.
Description check ✅ Passed The PR description covers the main objective, implementation details, and shortcut assignments, though CLA and testing checkboxes are not explicitly marked.
Linked Issues check ✅ Passed The code changes fully implement the requirements from issue #33670: adding a 'select-notes-in-chord' action that selects all notes in chords, with proper shortcut bindings and UI action registration.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the chord selection feature: shortcut definitions, action registration, and implementation logic with no extraneous modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Infer (1.2.0)
src/notationscene/internal/notationactioncontroller.cpp

In file included from src/notationscene/internal/notationactioncontroller.cpp:22:
src/notationscene/internal/notationactioncontroller.h:24:10: fatal error: 'async/asyncable.h' file not found
24 | #include "async/asyncable.h"
| ^~~~~~~~~~~~~~~~~~~
1 error generated.
src/notationscene/internal/notationactioncontroller.cpp:2376:5-12: ERROR translating statement 'ReturnStmt'
Aborting translation of method 'mu::notation::NotationActionController::isEditingElement' in file 'src/notationscene/internal/notationactioncontroller.cpp': "Assert_failure src/clang/cAst_utils.ml:249:53"
Aborting translation of method 'mu::notation::NotationActionController::isNotEditingElement' in file 'src/notationscene/internal/notationactioncontroller.cpp': "Assert_failure src/clang/cAst_utils.ml:249:53"
Aborting translation of method 'mu::notation::NotationActionController::init' in file 'src/notationscene/internal/notationactioncontroller.cpp': "Assert_failure src/clang/cAst_utils.ml:249:53"
Un

... [truncated 2200 characters] ...

Called from ClangFrontend__CTrans.CTrans_funct.instruction_insert_cxx_temporary_markers in file "src/clang/cTrans.ml", line 4866, characters 22-60
Called from ClangFrontend__CTrans.CTrans_funct.instruction_scope in file "src/clang/cTrans.ml", line 4850, characters 22-79
Called from ClangFrontend__CTrans.CTrans_funct.instruction_log.(fun) in file "src/clang/cTrans.ml", line 4782, characters 12-47
Re-raised at IStdlib__IExn.reraise_after in file "src/istd/IExn.ml" (inlined), line 13, characters 2-50
Called from ClangFrontend__CTrans.CTrans_funct.instruction_log.(fun) in file "src/clang/cTrans.ml", line 4784, characters 10-1023
Called from ClangFrontend__CTrans.CTrans_funct.instruction in file "src/clang/cTrans.ml" (inlined), line 4765, characters 38-71
Called from ClangFrontend__CTrans.CTra

src/notationscene/internal/notationuiactions.cpp

In file included from src/notationscene/internal/notationuiactions.cpp:22:
src/notationscene/internal/notationuiactions.h:24:10: fatal error: 'async/asyncable.h' file not found
24 | #include "async/asyncable.h"
| ^~~~~~~~~~~~~~~~~~~
1 error generated.
src/notationscene/internal/notationuiactions.cpp:2991:5-12: ERROR translating statement 'ReturnStmt'
Aborting translation of method 'mu::notation::NotationUiActions::actionChecked' in file 'src/notationscene/internal/notationuiactions.cpp': "Assert_failure src/clang/cAst_utils.ml:249:53"
Uncaught Internal Error: "Assert_failure src/clang/cAst_utils.ml:249:53"
Error backtrace:
Raised at ClangFrontend__CAst_utils.get_decl_from_typ_ptr in file "src/clang/cAst_utils.ml", line 249, characters 53-65
Called from ClangFrontend__CTrans.CTrans_funct.get_destructor_decl_ref in file "src/clang/cTrans.ml", line 658, characters 12-59
Called from ClangFrontend__CTrans.CTrans_funct.destructor_calls.(fun) in file "src/clang/cTrans.ml", l

... [truncated 2200 characters] ...

r in file "src/istd/IExn.ml" (inlined), line 13, characters 2-50
Called from ClangFrontend__CTrans.CTrans_funct.instruction_log.(fun) in file "src/clang/cTrans.ml", line 4784, characters 10-1023
Called from ClangFrontend__CTrans.CTrans_funct.instruction in file "src/clang/cTrans.ml" (inlined), line 4765, characters 38-71
Called from ClangFrontend__CTrans.CTrans_funct.exec_with_node_creation in file "src/clang/cTrans.ml" (inlined), line 104, characters 20-38
Called from ClangFrontend__CTrans.CTrans_funct.get_clang_stmt_trans in file "src/clang/cTrans.ml" (inlined), line 5395, characters 4-69
Called from ClangFrontend__CTrans.CTrans_funct.get_custom_stmt_trans in file "src/clang/cTrans.ml", line 5401, characters 8-55
Called from ClangFrontend__CTrans.CTrans_funct.exec_trans_instrs.exec_trans

Warning

Review ran into problems

🔥 Problems

Linked repositories: Your configuration references 1 linked repositories, but your current plan allows 0. 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 and usage tips.

@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

🤖 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`:
- Line 257: The action "notation-select-all-chord" is currently enabled by
Controller::hasSelection but only operates on notes; change the enabler to check
for a selected note instead. Replace the predicate in registerAction with a
Controller method that returns true only if the current selection contains at
least one note (e.g. &Controller::hasSelectedNote or implement
hasSelectedNote/hasNoteSelected on Controller to inspect the selection for note
elements) so registerAction("notation-select-all-chord",
&Controller::selectAllChordNotes, &Controller::hasSelectedNote) is used.
- Around line 1630-1663: The file uses std::set inside
NotationActionController::selectAllChordNotes() but doesn't include <set>,
relying on transitive includes; add a direct `#include` <set> to
src/notationscene/internal/notationactioncontroller.cpp (or the corresponding
header) alongside the other includes so std::set is declared for the function
and compilation no longer depends on transitive headers.
🪄 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: 659bc6f5-eddb-4750-b6c7-d8cbd941af31

📥 Commits

Reviewing files that changed from the base of the PR and between 626de86 and 5984409.

📒 Files selected for processing (6)
  • src/app/configs/data/shortcuts.xml
  • src/app/configs/data/shortcuts_azerty.xml
  • src/app/configs/data/shortcuts_mac.xml
  • src/notationscene/internal/notationactioncontroller.cpp
  • src/notationscene/internal/notationactioncontroller.h
  • src/notationscene/internal/notationuiactions.cpp

registerAction("select-similar-staff", &Controller::selectAllSimilarElementsInStaff, &Controller::hasSelection);
registerAction("select-similar-range", &Controller::selectAllSimilarElementsInRange, &Controller::hasSelection);
registerAction("select-dialog", &Controller::openSelectionMoreOptions, &Controller::hasSelection);
registerAction("notation-select-all-chord", &Controller::selectAllChordNotes, &Controller::hasSelection);

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Narrow the enabler to “has selected note” instead of generic selection.

The action is currently enabled for any selection, but it only acts on notes; non-note selections trigger a no-op. Gate this action on note presence to match its behavior and avoid misleading enabled state.

🤖 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` at line 257, The
action "notation-select-all-chord" is currently enabled by
Controller::hasSelection but only operates on notes; change the enabler to check
for a selected note instead. Replace the predicate in registerAction with a
Controller method that returns true only if the current selection contains at
least one note (e.g. &Controller::hasSelectedNote or implement
hasSelectedNote/hasNoteSelected on Controller to inspect the selection for note
elements) so registerAction("notation-select-all-chord",
&Controller::selectAllChordNotes, &Controller::hasSelectedNote) is used.

Comment on lines +1630 to +1663
void NotationActionController::selectAllChordNotes()
{
TRACEFUNC;
auto interaction = currentNotationInteraction();
if (!interaction) {
return;
}

const std::vector<EngravingItem*>& selectedElements = interaction->selection()->elements();
if (selectedElements.empty()) {
return;
}

std::set<const Chord*> chords;
for (const EngravingItem* item : selectedElements) {
if (item->isNote()) {
chords.insert(toNote(item)->chord());
}
}

if (chords.empty()) {
return;
}

std::vector<EngravingItem*> allNotes;
for (const Chord* chord : chords) {
for (Note* note : chord->notes()) {
allNotes.push_back(note);
}
}

interaction->clearSelection();
interaction->select(allNotes, SelectType::ADD);
}

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.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify direct std::set usage and local include presence in notationactioncontroller.cpp
fd -p src/notationscene/internal/notationactioncontroller.cpp -x sh -c '
  f="$1"
  echo "== $f =="
  rg -n "std::set<|`#include` <set>" "$f"
' sh {}

Repository: musescore/MuseScore

Length of output: 167


🏁 Script executed:

#!/bin/bash
set -euo pipefail
f="src/notationscene/internal/notationactioncontroller.cpp"

echo "== includes near top =="
sed -n '1,120p' "$f" | nl -ba | sed -n '1,120p'

echo
echo "== any explicit <set> include in this file =="
rg -n "#\s*include\s*<set>|#\s*include\s*\"[^\"\n]*set[^\"\n]*\"" "$f" || true

echo
echo "== std::set usage (context) =="
rg -n "std::set<" "$f" -n -C 2

Repository: musescore/MuseScore

Length of output: 148


🏁 Script executed:

#!/bin/bash
set -euo pipefail
f="src/notationscene/internal/notationactioncontroller.cpp"

echo "== first 140 lines (includes area) =="
cat -n "$f" | sed -n '1,140p'

echo
echo "== explicit std::set include in this file =="
rg -n "^\s*#\s*include\s*<set>\s*$" "$f" || true

echo
echo "== any <set> substring includes =="
rg -n "^\s*#\s*include\s*<[^>]*set[^>]*>\s*$|^\s*#\s*include\s*\"[^\"]*set[^\"]*\"\s*$" "$f" || true

echo
echo "== std::set usage (with context) =="
rg -n "std::set<" "$f" -C 2

Repository: musescore/MuseScore

Length of output: 7630


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the header that is included as "notationactioncontroller.h"
hdr="$(fd -t f -i 'notationactioncontroller\.h$' src | head -n 1)"
echo "== header candidate =="
echo "$hdr"

echo
echo "== explicit <set> include in header =="
rg -n "^\s*#\s*include\s*<set>\s*$" "$hdr" || true

echo
echo "== any <...set...> include lines in header =="
rg -n "^\s*#\s*include\s*<[^>]*set[^>]*>\s*$" "$hdr" || true

Repository: musescore/MuseScore

Length of output: 227


Add missing direct #include <set> for std::set

selectAllChordNotes() uses std::set, but neither src/notationscene/internal/notationactioncontroller.cpp nor src/notationscene/internal/notationactioncontroller.h includes <set>, so the build currently relies on transitive includes.

Suggested patch
 `#include` "io/file.h"
+#include <set>
 
 `#include` "engraving/dom/masterscore.h"
 `#include` "engraving/dom/note.h"
 `#include` "engraving/dom/chord.h"
🤖 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 1630 -
1663, The file uses std::set inside
NotationActionController::selectAllChordNotes() but doesn't include <set>,
relying on transitive includes; add a direct `#include` <set> to
src/notationscene/internal/notationactioncontroller.cpp (or the corresponding
header) alongside the other includes so std::set is declared for the function
and compilation no longer depends on transitive headers.

@mathesoncalum mathesoncalum 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.

Take a look at NotationViewInputController::mouseDoubleClickEvent - this method already has some logic for selecting an entire chord. I think we should avoid repeating this logic in multiple places if possible.

I reckon it'll just be a case of carefully checking the logic we already have, ensuring that the new NotationActionController::selectAllChordNotes doesn't miss any cases covered by the original method, and then simply calling dispatcher()->dispatch("notation-select-all-chord"... from mouseDoubleClickEvent.

Also I'm not crazy about notation-select-all-chord as a name - IMO that could be confused for "selecting all chords". Maybe select-notes-in-chord or something like that.

Cheers!

notation-select-all-chord -> select-notes-in-chord
selectAllChordNotes -> selectAllNotesInChord

Reorganize shortcut entry under select-* actions
@JohannJEG

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback.

I agree that select-notes-in-chord is a clearer name than notation-select-all-chord, so I've renamed the action and related method accordingly.

Regarding the dispatch() suggestion, I reviewed mouseDoubleClickEvent(). The note double-click path currently handles additional behavior such as ADD selection and toggle/deselect when all notes in the chord are already selected, while this action is intended to expand the current selection to the notes of the selected chord(s).

Due to those behavioral differences, I wasn't sure a direct replacement through dispatch() would preserve the current double-click behavior without additional refactoring.

I do think there may be value in refactoring mouseDoubleClickEvent() into smaller handlers and exploring shared logic there, but that feels like a separate cleanup/refactor PR rather than part of this shortcut feature.

If you think the dispatch-based approach is still preferable, I'm happy to take another look.

@mathesoncalum

Copy link
Copy Markdown
Contributor

Ah that is an interesting point - I just assumed that deselection would be part-and-parcel of this, but maybe not.

@avvvvve what do you reckon? For example if I have an entire chord selected already and I press Cmd+Opt+A should that then deselect the entire chord? Maybe that gets gnarly when you have a mixed selection across different chords...

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.

Add shortcut action 'Select all notes in chord'

3 participants