-
Notifications
You must be signed in to change notification settings - Fork 76
Multiple notes can now be selected with keyboard, by pressing Shift+A… #526
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2072,11 +2072,37 @@ bool PowerTabEditor::eventFilter(QObject *object, QEvent *event) | |
| if (myIsPlaying) | ||
| return QMainWindow::eventFilter(object, event); | ||
|
|
||
| // Only handle key events. | ||
| QKeyEvent *keyEvent = dynamic_cast<QKeyEvent *>(event); | ||
| if (keyEvent == nullptr) { | ||
| return QMainWindow::eventFilter(object, event); | ||
| } | ||
|
|
||
| // Anly handle key presses that influence the score area, i.e. if the score area is | ||
| // the active widget | ||
| ScoreArea *scorearea = getScoreArea(); | ||
| if (scorearea && event->type() == QEvent::KeyPress) | ||
| if (!scorearea) | ||
| { | ||
| QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); | ||
| if (keyEvent->key() >= Qt::Key_0 && keyEvent->key() <= Qt::Key_9) | ||
| return QMainWindow::eventFilter(object, event); | ||
| } | ||
|
|
||
|
|
||
| if (event->type() == QEvent::KeyRelease) | ||
| { | ||
| if (keyEvent->key() == Qt::Key_Shift || keyEvent->key() == Qt::Key_Alt) | ||
| { | ||
| // If either of these keys are released, the current selection cycle should end. | ||
| myIsCurrentlyDoingNoteSelectionWithKeyboard = false; | ||
| } | ||
| } | ||
| else if (event->type() == QEvent::KeyPress) | ||
| { | ||
| // Method call returns true if selection event was handled. | ||
| if (handleKeyboardNoteSelectionEvent(keyEvent)) | ||
| { | ||
| return true; | ||
| } | ||
| else if (keyEvent->key() >= Qt::Key_0 && keyEvent->key() <= Qt::Key_9) | ||
| { | ||
| const int number = keyEvent->key() - Qt::Key_0; | ||
| ScoreLocation &location = getLocation(); | ||
|
|
@@ -2136,6 +2162,36 @@ bool PowerTabEditor::eventFilter(QObject *object, QEvent *event) | |
| return QMainWindow::eventFilter(object, event); | ||
| } | ||
|
|
||
| bool PowerTabEditor::handleKeyboardNoteSelectionEvent(QKeyEvent* keyEvent) | ||
| { | ||
| // Keyboard selection should only be handled if all of 'Shift + Alt + an arrow key' are pressed, | ||
| // and only if the arrow key is left or right. | ||
| Qt::KeyboardModifiers selectionModifiers = Qt::ShiftModifier | Qt::AltModifier | Qt::KeypadModifier; | ||
|
|
||
| if (keyEvent->keyCombination().keyboardModifiers() != selectionModifiers | ||
| || (keyEvent->key() != Qt::Key_Left && keyEvent->key() != Qt::Key_Right)) { | ||
| return false; | ||
| } | ||
|
|
||
| ScoreLocation& location = getLocation(); | ||
| int currentPosIndex = location.getPositionIndex(); | ||
|
|
||
| // If this is the first selection event, we set the selection start, and signal selection of | ||
| // the current position before advancing the caret. | ||
| if (! myIsCurrentlyDoingNoteSelectionWithKeyboard) { | ||
| myIsCurrentlyDoingNoteSelectionWithKeyboard = true; | ||
| location.setSelectionStart(currentPosIndex); | ||
| getScoreArea()->getClickEvent().signal(ScoreItem::Staff, location, ScoreItemAction::Selected); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't tested, but I'm not entirely sure if this is necessary - it feels a bit awkward to be faking a click event.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at this a bit more, I think you want to go through the |
||
| } | ||
|
|
||
| int direction = (keyEvent->key() == Qt::Key_Left) ? -1 : 1; | ||
| int newPosIndex = fmin(fmax(currentPosIndex + direction, 0), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something like |
||
| location.getSystem().getBarlines().back().getPosition() - 1); | ||
| location.setPositionIndex(newPosIndex); | ||
| getScoreArea()->getClickEvent().signal(ScoreItem::Staff, location, ScoreItemAction::Selected); | ||
| return true; | ||
| } | ||
|
|
||
| void PowerTabEditor::closeEvent(QCloseEvent *event) | ||
| { | ||
| while (myTabWidget->currentIndex() != -1) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -273,7 +273,9 @@ private slots: | |
| void info(void); | ||
|
|
||
| protected: | ||
| /// Handle key presses for 0-9 when entering tab numbers. | ||
| /// Main event handler. Currently handles: | ||
| /// - key presses for 0-9 when entering tab numbers. | ||
| /// - key presses related to multi-selection of notes (see dedicated method ``handleKeyboardNoteSelectionEvent``). | ||
| virtual bool eventFilter(QObject *object, QEvent *event) override; | ||
|
|
||
| /// Performs some final actions before exiting. | ||
|
|
@@ -420,6 +422,11 @@ private slots: | |
| /// Increases or decreases the line spacing by the given amount. | ||
| void adjustLineSpacing(int amount); | ||
|
|
||
| /// Handles events related to the multiselection of consecutive notes. Returns true if a fitting event was found and handled. | ||
| bool handleKeyboardNoteSelectionEvent(QKeyEvent* keyEvent); | ||
| /// A boolean helper flag for the above method. | ||
| bool myIsCurrentlyDoingNoteSelectionWithKeyboard; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is uninitialized currently - just doing Also, for a less verbose name perhaps something like
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the name is indeed too long. As for the initial value: An (incorrect) assumption on my part, I was under the impression that bools are initialized to false - a quick search proved that wrong, thanks. Probably also a conflation of different languages. |
||
|
|
||
| /// Returns the score area for the active document. | ||
| ScoreArea *getScoreArea(); | ||
| /// Returns the caret for the active document. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to avoid having a misleading comment,
getScoreArea()would be null only when there aren't any open documents (I don't think focus would affect it, that just affects whether key event make it to the root window's event handler)