diff --git a/libmscore/layout.cpp b/libmscore/layout.cpp index b4d01d1544905..f8bba8f808873 100644 --- a/libmscore/layout.cpp +++ b/libmscore/layout.cpp @@ -1428,12 +1428,14 @@ static void checkDivider(bool left, System* s, qreal yOffset) static void layoutPage(Page* page, qreal restHeight) { - Score* score = page->score(); - int nsystems = page->systems().size() - 1; +// Q_ASSERT(restHeight >= 0); + + Score* score = page->score(); + int gaps = page->systems().size() - 1; QList sList; - for (int i = 0; i < nsystems; ++i) { + for (int i = 0; i < gaps; ++i) { System* s1 = page->systems().at(i); System* s2 = page->systems().at(i+1); s1->setDistance(s2->y() - s1->y()); @@ -1465,14 +1467,12 @@ static void layoutPage(Page* page, qreal restHeight) } std::sort(sList.begin(), sList.end(), [](System* a, System* b) { return a->distance() < b->distance(); }); - qreal maxDist = score->styleP(Sid::maxSystemDistance); qreal dist = sList[0]->distance(); for (int i = 1; i < sList.size(); ++i) { qreal ndist = sList[i]->distance(); - qreal fill = ndist - dist; - dist = ndist; + qreal fill = ndist - dist; if (fill > 0.0) { qreal totalFill = fill * i; if (totalFill > restHeight) { @@ -1490,11 +1490,12 @@ static void layoutPage(Page* page, qreal restHeight) if (restHeight <= 0) break; } + dist = ndist; } + if (restHeight > 0.0) { qreal fill = restHeight / sList.size(); - for (int i = 0; i < sList.size(); ++i) { - System* s = sList[i]; + for (System* s : sList) { qreal d = s->distance() + fill; if ((d - s->height()) > maxDist) d = qMax(maxDist + s->height(), s->distance()); @@ -1503,7 +1504,7 @@ static void layoutPage(Page* page, qreal restHeight) } qreal y = page->systems().at(0)->y(); - for (int i = 0; i < nsystems; ++i) { + for (int i = 0; i < gaps; ++i) { System* s1 = page->systems().at(i); System* s2 = page->systems().at(i+1); s1->rypos() = y; @@ -3603,11 +3604,11 @@ void LayoutContext::collectPage() dist += vbox->bottomGap(); else if (!prevSystem->hasFixedDownDistance()) dist += qMax(curSystem->minBottom(), slb); + breakPage = (y + dist) >= ey && breakPages; } if (breakPage) { - Box* vbox = prevSystem->vbox(); - qreal dist = vbox ? vbox->bottomGap() : qMax(-prevSystem->minBottom(), slb); + qreal dist = qMax(prevSystem->minBottom(), slb); layoutPage(page, ey - (y + dist)); break; } diff --git a/libmscore/mscore.cpp b/libmscore/mscore.cpp index c8dc78c73346f..c651e94f53d6c 100644 --- a/libmscore/mscore.cpp +++ b/libmscore/mscore.cpp @@ -71,6 +71,7 @@ bool MScore::showMeasureShapes = false; bool MScore::noHorizontalStretch = false; bool MScore::noVerticalStretch = false; bool MScore::showBoundingRect = false; +bool MScore::showSystemBoundingRect = false; bool MScore::showCorruptedMeasures = true; bool MScore::useFallbackFont = true; bool MScore::autoplaceSlurs = true; diff --git a/libmscore/mscore.h b/libmscore/mscore.h index 143b49bd71f9d..98824d2b48855 100644 --- a/libmscore/mscore.h +++ b/libmscore/mscore.h @@ -370,6 +370,7 @@ class MScore : public QObject { static bool showSkylines; static bool showMeasureShapes; static bool showBoundingRect; + static bool showSystemBoundingRect; static bool showCorruptedMeasures; static bool useFallbackFont; static bool autoplaceSlurs; diff --git a/libmscore/system.cpp b/libmscore/system.cpp index b4e30699e9111..c768e506d407f 100644 --- a/libmscore/system.cpp +++ b/libmscore/system.cpp @@ -1060,7 +1060,7 @@ qreal System::minDistance(System* s2) const if (vbox() && !s2->vbox()) return qMax(vbox()->bottomGap(), s2->minTop()); else if (!vbox() && s2->vbox()) - return qMax(s2->vbox()->topGap(), -minBottom()); + return qMax(s2->vbox()->topGap(), minBottom()); else if (vbox() && s2->vbox()) return s2->vbox()->topGap() + vbox()->bottomGap(); @@ -1138,6 +1138,34 @@ qreal System::bottomDistance(int staffIdx, const SkylineLine& s) const return staff(staffIdx)->skyline().south().minDistance(s); } +//--------------------------------------------------------- +// firstVisibleSysStaff +//--------------------------------------------------------- + +SysStaff* System::firstVisibleSysStaff() const + { + for (SysStaff* s : _staves) { + if (s->show()) + return s; + } + qDebug("no sys staff"); + return 0; + } + +//--------------------------------------------------------- +// lastVisibleSysStaff +//--------------------------------------------------------- + +SysStaff* System::lastVisibleSysStaff() const + { + for (int i = _staves.size() - 1; i >= 0; --i) { + if (_staves[i]->show()) + return _staves[i]; + } + qDebug("no sys staff"); + return 0; + } + //--------------------------------------------------------- // minTop // Return the minimum top margin. @@ -1145,7 +1173,10 @@ qreal System::bottomDistance(int staffIdx, const SkylineLine& s) const qreal System::minTop() const { - return -staff(0)->skyline().north().max(); + SysStaff* s = firstVisibleSysStaff(); + if (s) + return -s->skyline().north().max(); + return 0.0; } //--------------------------------------------------------- @@ -1155,7 +1186,12 @@ qreal System::minTop() const qreal System::minBottom() const { - return -staves()->back()->skyline().south().max(); + if (vbox()) + return vbox()->height() + vbox()->bottomGap(); + SysStaff* s = lastVisibleSysStaff(); + if (s) + return s->skyline().south().max(); + return 0.0; } //--------------------------------------------------------- diff --git a/libmscore/system.h b/libmscore/system.h index 81b649ef5d7bb..13d13d8b9fa3a 100644 --- a/libmscore/system.h +++ b/libmscore/system.h @@ -89,6 +89,9 @@ class System final : public Element { mutable bool fixedDownDistance { false }; qreal _distance; // temp. variable used during layout + SysStaff* firstVisibleSysStaff() const; + SysStaff* lastVisibleSysStaff() const; + public: System(Score*); ~System(); diff --git a/mscore/musescore.cpp b/mscore/musescore.cpp index e171ed99047eb..2c7b118b4aa36 100644 --- a/mscore/musescore.cpp +++ b/mscore/musescore.cpp @@ -1674,6 +1674,9 @@ MuseScore::MuseScore() a = getAction("show-bounding-rect"); a->setCheckable(true); menuDebug->addAction(a); + a = getAction("show-system-bounding-rect"); + a->setCheckable(true); + menuDebug->addAction(a); a = getAction("show-corrupted-measures"); a->setCheckable(true); a->setChecked(true); @@ -5829,6 +5832,13 @@ void MuseScore::cmd(QAction* a, const QString& cmd) cs->update(); } } + else if (cmd == "show-system-bounding-rect") { + MScore::showSystemBoundingRect = a->isChecked(); + if (cs) { + cs->setLayoutAll(); + cs->update(); + } + } else if (cmd == "show-corrupted-measures") { MScore::showCorruptedMeasures = a->isChecked(); if (cs) { diff --git a/mscore/scoreview.cpp b/mscore/scoreview.cpp index 86c49c1173402..3b8a5be590b6c 100644 --- a/mscore/scoreview.cpp +++ b/mscore/scoreview.cpp @@ -1116,6 +1116,16 @@ void ScoreView::paint(const QRect& r, QPainter& p) #ifndef NDEBUG if (!score()->printing()) { + if (MScore::showSystemBoundingRect) { + for (const System* system : page->systems()) { + QPointF pt(system->ipos()); + qreal h = system->minBottom() + system->minTop(); + p.translate(pt); + QRectF r(0.0, -system->minTop(), system->width(), h); + p.drawRect(r); + p.translate(-pt); + } + } if (MScore::showSegmentShapes) { for (const System* system : page->systems()) { for (const MeasureBase* mb : system->measures()) { diff --git a/mscore/shortcut.cpp b/mscore/shortcut.cpp index 8d60192bf8694..c5e2d36a21b25 100644 --- a/mscore/shortcut.cpp +++ b/mscore/shortcut.cpp @@ -3635,6 +3635,16 @@ Shortcut Shortcut::_sc[] = { Icons::Invalid_ICON, Qt::ApplicationShortcut }, + { + MsWidget::MAIN_WINDOW, + STATE_ALL, + "show-system-bounding-rect", + "Show System Bounding Rectangles", + "Show bounding rectangles for systems", + 0, + Icons::Invalid_ICON, + Qt::ApplicationShortcut + }, { MsWidget::MAIN_WINDOW, STATE_ALL, diff --git a/mscore/workspace.cpp b/mscore/workspace.cpp index 19f693d55570c..2feef738317fa 100644 --- a/mscore/workspace.cpp +++ b/mscore/workspace.cpp @@ -204,6 +204,7 @@ void Workspace::initWorkspace() break; } } + Q_ASSERT(!Workspace::workspaces().empty()); if (currentWorkspace == 0) currentWorkspace = Workspace::workspaces().at(0); }