From 510fbf6ffcaf8f1d3b01cb111a98eb01d046b978 Mon Sep 17 00:00:00 2001 From: regulus79 <117475203+regulus79@users.noreply.github.com> Date: Sat, 26 Apr 2025 18:26:26 -0400 Subject: [PATCH] Global Spacebar Play (#7762) This PR refactors how the spacebar is handled by the editors and the MainWindow to allow it to play/stop (Shift+Space for play/pause) the last played editor, no matter if it is in focus or not. --------- Co-authored-by: Fawn Co-authored-by: Sotonye Atemie --- include/Editor.h | 13 +++++++------ include/MixerChannelView.h | 2 +- include/Song.h | 2 ++ src/core/Song.cpp | 3 +++ src/gui/EffectRackView.cpp | 1 + src/gui/EffectView.cpp | 1 + src/gui/MainWindow.cpp | 25 +++++++++++++++++++++++++ src/gui/MixerChannelView.cpp | 22 ++++++++++------------ src/gui/MixerView.cpp | 11 ++--------- src/gui/editors/AutomationEditor.cpp | 1 + src/gui/editors/Editor.cpp | 11 ++++++++++- src/gui/editors/PatternEditor.cpp | 2 ++ src/gui/editors/PianoRoll.cpp | 1 + 13 files changed, 66 insertions(+), 29 deletions(-) diff --git a/include/Editor.h b/include/Editor.h index a5b667166..46caab538 100644 --- a/include/Editor.h +++ b/include/Editor.h @@ -57,6 +57,13 @@ protected: DropToolBar * addDropToolBar(QWidget * parent, Qt::ToolBarArea whereToAdd, QString const & windowTitle); void closeEvent(QCloseEvent * event) override; + void keyPressEvent(QKeyEvent *ke) override; +public slots: + //! Called by pressing the space key. Plays or stops. + void togglePlayStop(); + //! Called by pressing shift+space. Toggles pause state. + void togglePause(); + protected slots: virtual void play() {} virtual void record() {} @@ -65,12 +72,6 @@ protected slots: virtual void stop() {} private slots: - /// Called by pressing the space key. Plays or stops. - void togglePlayStop(); - - /// Called by pressing shift+space. Toggles pause state. - void togglePause(); - void toggleMaximize(); signals: diff --git a/include/MixerChannelView.h b/include/MixerChannelView.h index e9ee1eddb..ed0d4f1ff 100644 --- a/include/MixerChannelView.h +++ b/include/MixerChannelView.h @@ -61,7 +61,7 @@ public: void contextMenuEvent(QContextMenuEvent*) override; void mousePressEvent(QMouseEvent*) override; void mouseDoubleClickEvent(QMouseEvent*) override; - bool eventFilter(QObject* dist, QEvent* event) override; + void keyPressEvent(QKeyEvent* ke) override; void reset(); int channelIndex() const { return m_channelIndex; } diff --git a/include/Song.h b/include/Song.h index f08edfff6..7fedaa44d 100644 --- a/include/Song.h +++ b/include/Song.h @@ -257,6 +257,7 @@ public: return m_playMode; } + PlayMode lastPlayMode() const { return m_lastPlayMode; } inline PlayPos & getPlayPos( PlayMode pm ) { return m_playPos[static_cast(pm)]; @@ -492,6 +493,7 @@ private: std::array m_timelines; PlayMode m_playMode; + PlayMode m_lastPlayMode; PlayPos m_playPos[PlayModeCount]; bar_t m_length; diff --git a/src/core/Song.cpp b/src/core/Song.cpp index ea60e349b..c2e027003 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -493,6 +493,7 @@ void Song::playSong() } m_playMode = PlayMode::Song; + m_lastPlayMode = m_playMode; m_playing = true; m_paused = false; @@ -532,6 +533,7 @@ void Song::playPattern() } m_playMode = PlayMode::Pattern; + m_lastPlayMode = m_playMode; m_playing = true; m_paused = false; @@ -558,6 +560,7 @@ void Song::playMidiClip( const MidiClip* midiClipToPlay, bool loop ) if( m_midiClipToPlay != nullptr ) { m_playMode = PlayMode::MidiClip; + m_lastPlayMode = m_playMode; m_playing = true; m_paused = false; } diff --git a/src/gui/EffectRackView.cpp b/src/gui/EffectRackView.cpp index 6a4b3124d..c6d62b334 100644 --- a/src/gui/EffectRackView.cpp +++ b/src/gui/EffectRackView.cpp @@ -65,6 +65,7 @@ EffectRackView::EffectRackView( EffectChain* model, QWidget* parent ) : auto addButton = new QPushButton; addButton->setText( tr( "Add effect" ) ); + addButton->setFocusPolicy(Qt::NoFocus); effectsLayout->addWidget( addButton ); diff --git a/src/gui/EffectView.cpp b/src/gui/EffectView.cpp index a5095ee6d..dee9eb136 100644 --- a/src/gui/EffectView.cpp +++ b/src/gui/EffectView.cpp @@ -93,6 +93,7 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : QFont f = ctls_btn->font(); ctls_btn->setFont(adjustedToPixelSize(f, DEFAULT_FONT_SIZE)); ctls_btn->setGeometry( 150, 14, 50, 20 ); + ctls_btn->setFocusPolicy(Qt::NoFocus); connect( ctls_btn, SIGNAL(clicked()), this, SLOT(editControls())); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 7ca1387bf..b012eca7a 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1287,6 +1287,31 @@ void MainWindow::keyPressEvent( QKeyEvent * _ke ) case Qt::Key_Control: m_keyMods.m_ctrl = true; break; case Qt::Key_Shift: m_keyMods.m_shift = true; break; case Qt::Key_Alt: m_keyMods.m_alt = true; break; + case Qt::Key_Space: + { + Editor* lastEditor = nullptr; + switch (Engine::getSong()->lastPlayMode()) + { + case Song::PlayMode::Song: + lastEditor = getGUI()->songEditor(); + break; + case Song::PlayMode::MidiClip: + lastEditor = getGUI()->pianoRoll(); + break; + case Song::PlayMode::Pattern: + lastEditor = getGUI()->patternEditor(); + break; + case Song::PlayMode::AutomationClip: + lastEditor = getGUI()->automationEditor(); + break; + default: + lastEditor = getGUI()->songEditor(); + break; + } + if (m_keyMods.m_shift) { lastEditor->togglePause(); } + else { lastEditor->togglePlayStop(); } + break; + } default: { InstrumentTrackWindow * w = diff --git a/src/gui/MixerChannelView.cpp b/src/gui/MixerChannelView.cpp index ccfb5c75c..13b18ce4b 100644 --- a/src/gui/MixerChannelView.cpp +++ b/src/gui/MixerChannelView.cpp @@ -147,6 +147,8 @@ MixerChannelView::MixerChannelView(QWidget* parent, MixerView* mixerView, int ch mainLayout->addWidget(m_fader, 1, Qt::AlignHCenter); connect(m_renameLineEdit, &QLineEdit::editingFinished, this, &MixerChannelView::renameFinished); + + setFocusPolicy(Qt::StrongFocus); } void MixerChannelView::contextMenuEvent(QContextMenuEvent*) @@ -220,23 +222,19 @@ void MixerChannelView::mouseDoubleClickEvent(QMouseEvent*) renameChannel(); } -bool MixerChannelView::eventFilter(QObject*, QEvent* event) +void MixerChannelView::keyPressEvent(QKeyEvent* ke) { - // If we are in a rename, capture the enter/return events and handle them - if (event->type() == QEvent::KeyPress) + if (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return) { - auto keyEvent = static_cast(event); - if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) + if (m_inRename) { - if (m_inRename) - { - renameFinished(); - event->accept(); // Stop the event from propagating - return true; - } + renameFinished(); } } - return false; + else if (ke->key() == Qt::Key_Space) + { + m_fader->adjustByDialog(); + } } void MixerChannelView::setChannelIndex(int index) diff --git a/src/gui/MixerView.cpp b/src/gui/MixerView.cpp index e0b483bd6..fd6391bf0 100644 --- a/src/gui/MixerView.cpp +++ b/src/gui/MixerView.cpp @@ -536,15 +536,8 @@ void MixerView::keyPressEvent(QKeyEvent * e) case Qt::Key_F2: renameChannel(m_currentMixerChannel->channelIndex()); break; - case Qt::Key_Space: - { - auto* mixerChannel = currentMixerChannel(); - - if (mixerChannel) - { - mixerChannel->fader()->adjustByDialog(); - } - } + default: + e->ignore(); break; } } diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index 1239da55e..c90f45a86 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -287,6 +287,7 @@ void AutomationEditor::keyPressEvent(QKeyEvent * ke ) break; default: + ke->ignore(); break; } } diff --git a/src/gui/editors/Editor.cpp b/src/gui/editors/Editor.cpp index c32fb5437..750a28fc2 100644 --- a/src/gui/editors/Editor.cpp +++ b/src/gui/editors/Editor.cpp @@ -118,7 +118,6 @@ Editor::Editor(bool record, bool stepRecord) : connect(m_recordAccompanyAction, SIGNAL(triggered()), this, SLOT(recordAccompany())); connect(m_toggleStepRecordingAction, SIGNAL(triggered()), this, SLOT(toggleStepRecording())); connect(m_stopAction, SIGNAL(triggered()), this, SLOT(stop())); - new QShortcut(Qt::Key_Space, this, SLOT(togglePlayStop())); new QShortcut(QKeySequence(combine(Qt::SHIFT, Qt::Key_Space)), this, SLOT(togglePause())); new QShortcut(QKeySequence(combine(Qt::SHIFT, Qt::Key_F11)), this, SLOT(toggleMaximize())); @@ -155,6 +154,16 @@ void Editor::closeEvent(QCloseEvent * event) event->ignore(); } + void Editor::keyPressEvent(QKeyEvent *ke) + { + if (ke->key() == Qt::Key_Space) + { + togglePlayStop(); + return; + } + ke->ignore(); + } + DropToolBar::DropToolBar(QWidget* parent) : QToolBar(parent) { setAcceptDrops(true); diff --git a/src/gui/editors/PatternEditor.cpp b/src/gui/editors/PatternEditor.cpp index 291578698..42bb47e9c 100644 --- a/src/gui/editors/PatternEditor.cpp +++ b/src/gui/editors/PatternEditor.cpp @@ -49,6 +49,8 @@ PatternEditor::PatternEditor(PatternStore* ps) : m_ps(ps) { setModel(ps); + setFocusPolicy(Qt::StrongFocus); + setFocus(); } diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 9dba3e7f0..db8ae6144 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -1505,6 +1505,7 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke) } break; default: + ke->ignore(); break; }