Allow PianoRoll to open empty again, but with a help icon (#8148)

Fixes #8152

Revert PianoRoll closing when empty (caused issues with detached windows)
Remove TextFloat warning when there are no instruments/multiple clips (showed up when reloading project)
(Keep clip creation for empty projects)
Add an icon and updated message in empty PianoRoll.
Mark PianoRollWindow invalid when there is no clip, making buttons impossible to click

---------

Co-authored-by: Fawn <rubiefawn@gmail.com>
This commit is contained in:
Alex
2025-12-14 14:40:35 +01:00
committed by GitHub
parent 8627616175
commit 0ffcfe3bff
5 changed files with 77 additions and 38 deletions

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1" width="157.443" height="71.502" viewBox="0 0 41.657 18.918">
<metadata>
<rdf:RDF>
<cc:Work>
<dc:title>Graphic for piano roll without clip</dc:title>
<dc:creator><cc:Agent><dc:title>allejok96</dc:title></cc:Agent></dc:creator>
</cc:Work>
<cc:License rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
<defs>
<linearGradient id="a">
<stop offset="0" stop-color="#6eb8c8"/>
<stop offset="1" stop-color="#2f4e55"/>
</linearGradient>
<linearGradient xlink:href="#a" id="b" x1="87.18" x2="87.18" y1="76.323" y2="80.715" gradientTransform="translate(-65.48 -71.948)" gradientUnits="userSpaceOnUse"/>
</defs>
<g fill="url(#b)" opacity="0.63">
<path d="M14.086 4.345v4.316h10.14V4.345z"/>
<path d="M24.6 4.345v4.316h6.083c.002-.404.01-.808.034-1.21.095-.807.636-1.714 1.53-1.752.188-.013.363.013.523.07V4.344z"/>
</g>
<g fill="#49515b">
<path d="M32.323 6.173c-.593 0-1.07.732-1.07 1.642v6.52l-1.107-1.108c-.35-.35-.968-.294-1.387.125l-.05.05c-.419.418-.475 1.037-.125 1.386l3.242 3.242c.09.09.196.152.313.19a3.797 1.964 0 0 0 2.903.698 3.797 1.964 0 0 0 3.765-1.745 1.079 1.079 0 0 0 .036-.279v-5.16c0-.556-.413-1.004-.926-1.004h-.06c-.463 0-.844.364-.915.843-.07-.48-.452-.843-.914-.843h-.061a.915.915 0 0 0-.808.511.915.915 0 0 0-.807-.511h-.061a.92.92 0 0 0-.829.554V7.815c0-.91-.477-1.642-1.069-1.642z"/>
<path d="M.012 0A.016.016 0 0 0 0 .016v2.49c0 .01.007.016.016.016h41.625a.016.016 0 0 0 .016-.016V.016A.015.015 0 0 0 41.64 0H.013zm39.661.447h.308l.424.6.421-.6h.305l-.57.778.6.813h-.307l-.449-.635-.455.635h-.305l.597-.813zM0 3.022v12.727h28.8c-.236-.222-.478-.44-.674-.694H13.649v-5.22h17.078l-.006-.74H13.65v-5.22h27.293v5.22h-6.95c-.002.247-.005.494-.005.74h6.955v5.22H39.37l.003.639-.003.055h2.287V3.022Zm2.772 3.015H10.2a.04.04 0 0 1 .04.04v.817a.04.04 0 0 1-.04.04H2.772a.04.04 0 0 1-.04-.04v-.817a.04.04 0 0 1 .04-.04zm0 5.96H10.2a.04.04 0 0 1 .04.04v.817a.04.04 0 0 1-.04.04H2.772a.039.039 0 0 1-.04-.04v-.818a.04.04 0 0 1 .04-.04z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1" width="157.443" height="71.502" viewBox="0 0 41.657 18.918">
<metadata>
<rdf:RDF>
<cc:Work>
<dc:title>Graphic for piano roll without clip</dc:title>
<dc:creator><cc:Agent><dc:title>allejok96</dc:title></cc:Agent></dc:creator>
</cc:Work>
<cc:License rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
<g fill="#fff" opacity=".2">
<path d="M32.323 6.173c-.593 0-1.07.732-1.07 1.642v6.52l-1.107-1.108c-.35-.35-.968-.294-1.387.125l-.05.05c-.419.418-.475 1.037-.125 1.386l3.242 3.242c.09.09.196.152.313.19a3.797 1.964 0 0 0 2.903.698 3.797 1.964 0 0 0 3.765-1.745 1.079 1.079 0 0 0 .036-.279v-5.16c0-.556-.413-1.004-.926-1.004h-.06c-.463 0-.844.364-.915.843-.07-.48-.452-.843-.914-.843h-.061a.915.915 0 0 0-.808.511.915.915 0 0 0-.807-.511h-.061a.92.92 0 0 0-.829.554V7.815c0-.91-.477-1.642-1.069-1.642z" />
<path d="M.012 0A.016.016 0 0 0 0 .016v2.49c0 .01.007.016.016.016h41.625a.016.016 0 0 0 .016-.016V.016A.015.015 0 0 0 41.64 0H.013zm39.661.447h.308l.424.6.421-.6h.305l-.57.778.6.813h-.307l-.449-.635-.455.635h-.305l.597-.813zM0 3.022v12.727h28.8c-.236-.222-.478-.44-.674-.694H13.649v-5.22h17.078l-.006-.74H13.65v-5.22h27.293v5.22h-6.95c-.002.247-.005.494-.005.74h6.955v5.22H39.37l.003.639-.003.055h2.287V3.022Zm14.111 1.255v4.316h10.141V4.277Zm10.526.014v4.315h6.083c.002-.404.01-.807.033-1.21.096-.807.636-1.713 1.53-1.75a1.29 1.29 0 0 1 .524.068V4.29zM2.772 6.037H10.2a.04.04 0 0 1 .04.04v.817a.04.04 0 0 1-.04.04H2.772a.04.04 0 0 1-.04-.04v-.817a.04.04 0 0 1 .04-.04zm0 5.96H10.2a.04.04 0 0 1 .04.04v.817a.04.04 0 0 1-.04.04H2.772a.039.039 0 0 1-.04-.04v-.818a.04.04 0 0 1 .04-.04z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -146,7 +146,6 @@ 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;

View File

@@ -919,7 +919,9 @@ void MainWindow::help()
void MainWindow::toggleWindow( QWidget *window, bool forceShow )
{
QWidget *parent = window->parentWidget();
// All "windows" should be inside a SubWindow, because the use of activeSubWindow() depends on it
auto parent = dynamic_cast<QMdiSubWindow*>(window->parentWidget());
if (parent == nullptr) { return; }
if( forceShow ||
m_workspace->activeSubWindow() != parent ||
@@ -927,7 +929,8 @@ void MainWindow::toggleWindow( QWidget *window, bool forceShow )
{
parent->show();
window->show();
window->setFocus();
if (window->isEnabled()) { window->setFocus(); }
else { m_workspace->setActiveSubWindow(parent); }
}
else
{

View File

@@ -3141,6 +3141,20 @@ void PianoRoll::paintEvent(QPaintEvent * pe )
// fill with bg color
p.fillRect( 0, 0, width(), height(), bgColor );
if (!hasValidMidiClip())
{
const auto icon = embed::getIconPixmap("pr_no_clip");
const int x = (width() - icon.width()) / 2;
const int y = (height() - icon.height()) / 2;
p.drawPixmap(x, y, icon);
p.setPen(QApplication::palette().color(QPalette::Active, QPalette::Text));
QRect textRect(0, y + icon.height() + 5, width(), 30);
p.drawText(textRect, Qt::AlignHCenter | Qt::AlignTop,
tr("Double-click on an instrument clip in Song Editor to open it here"));
return;
}
// set font-size to 80% of key line height
QFont f = p.font();
int keyFontSize = m_keyLineHeight * 0.8;
@@ -3725,17 +3739,6 @@ void PianoRoll::paintEvent(QPaintEvent * pe )
p.drawPoints( editHandles );
}
else
{
QFont f = font();
f.setBold(true);
p.setFont(f);
p.setPen( QApplication::palette().color( QPalette::Active,
QPalette::BrightText ) );
p.drawText(m_whiteKeyWidth + 20, PR_TOP_MARGIN + 40,
tr( "Please open a clip by double-clicking "
"on it!" ) );
}
p.setClipRect(
m_whiteKeyWidth,
@@ -4666,7 +4669,7 @@ void PianoRoll::updatePosition(const TimePos & t)
// > width = outside viewport right
const int pos = (static_cast<int>(m_timeLine->pos()) - m_currentPosition) * m_ppb / TimePos::ticksPerBar();
// if pos is within visible range, show it
if (pos >= 0 && pos <= width() - m_whiteKeyWidth)
if (hasValidMidiClip() && pos >= 0 && pos <= width() - m_whiteKeyWidth)
{
m_positionLine->show();
// adjust pos for piano keys width and self line width (align to rightmost of line)
@@ -5406,13 +5409,11 @@ 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.
// Has a clip already, do nothing
if (m_editor->hasValidMidiClip()) { return; }
InstrumentTrack* firstTrack = nullptr;
MidiClip* firstEmptyClip = nullptr;
@@ -5440,13 +5441,9 @@ void PianoRollWindow::showEvent(QShowEvent*)
{
firstMelodyClip = midiClip;
}
// If there are multiple non-empty clips in the Song, show a hint
// If there are multiple clips with notes, do nothing
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;
}
}
@@ -5461,24 +5458,13 @@ void PianoRollWindow::showEvent(QShowEvent*)
{
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;
}
setEnabled(m_editor->hasValidMidiClip());
m_editor->m_timeLine->setVisible(m_editor->hasValidMidiClip());
clipRenamed();
updateStepRecordingIcon(); //MIDI clip change turn step recording OFF - update icon accordingly