diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 8ef669286..5548d73ec 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -146,6 +146,7 @@ public: return m_midiClip; } + // TODO remove this since PianoRoll should no longer be visible without a valid midi clip bool hasValidMidiClip() const { return m_midiClip != nullptr; @@ -588,6 +589,8 @@ private slots: private: void clipRenamed(); void focusInEvent(QFocusEvent * event) override; + void showEvent(QShowEvent* se) override; + void stopStepRecording(); void updateStepRecordingIcon(); diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 37951bc37..145e8cc07 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -5388,8 +5388,82 @@ bool PianoRollWindow::hasFocus() const +void PianoRollWindow::showEvent(QShowEvent*) +{ + // PianoRoll can ONLY be shown if hasValidMidiClip is true + // TODO remove hasValidMidiClip checks throughout the code + if (m_editor->hasValidMidiClip()) { return; } + + // A new user might try to open PianoRoll in an empty project unaware that they first need to create a clip. + // To make life easier for them we create and/or open the first clip in an empty project. + // If there are multiple non-empty clips, we tell the user to double click one of them instead. + + InstrumentTrack* firstTrack = nullptr; + MidiClip* firstEmptyClip = nullptr; + MidiClip* firstMelodyClip = nullptr; + + // Iterate through all instrument tracks in the Song + for (auto track: Engine::getSong()->tracks()) + { + if (track->type() != Track::Type::Instrument) { continue; } + auto instrumentTrack = static_cast(track); + if (!firstTrack) { firstTrack = instrumentTrack; } + + // Iterate through all midi clips in each track + for (auto clip: instrumentTrack->getClips()) + { + auto midiClip = static_cast(clip); + + // Remember the first empty clip in the Song (ignore subsequent empty clips) + if (midiClip->notes().empty()) + { + if (!firstEmptyClip) { firstEmptyClip = midiClip; } + } + // Remember the first non-empty clip in the Song + else if (!firstMelodyClip) + { + firstMelodyClip = midiClip; + } + // If there are multiple non-empty clips in the Song, show a hint + else + { + TextFloat::displayMessage(tr("No clip selected"), + tr("Double click a melody clip in the Song Editor to open it."), + embed::getIconPixmap("error"), 5000); + parentWidget()->hide(); + return; + } + } + } + // If we found a clip, open it + if (firstMelodyClip || firstEmptyClip) + { + m_editor->setCurrentMidiClip(firstMelodyClip ? firstMelodyClip : firstEmptyClip); + } + // If we found a track with no clips, create a clip and open it + else if (firstTrack) + { + m_editor->setCurrentMidiClip(new MidiClip(firstTrack)); + } + // If we found no instrument tracks, show a hint + else + { + TextFloat::displayMessage(tr("No instrument tracks"), + tr("Drag an instrument plugin or preset from the sidebar to the Song Editor."), + embed::getIconPixmap("error"), 5000); + parentWidget()->hide(); + } +} + + void PianoRollWindow::updateAfterMidiClipChange() { + if (!m_editor->hasValidMidiClip()) + { + parentWidget()->hide(); + return; + } + clipRenamed(); updateStepRecordingIcon(); //MIDI clip change turn step recording OFF - update icon accordingly }