Move ScoreView's viewport to show the last score changes

This commit is contained in:
Dmitri Ovodok 2019-10-24 20:40:22 +02:00
parent 51e8517543
commit 7dc8ca53b9
4 changed files with 100 additions and 4 deletions

View file

@ -1000,8 +1000,11 @@ void ScoreView::changeState(ViewState s)
//
switch (s) {
case ViewState::NORMAL:
if (state == ViewState::EDIT)
if (state == ViewState::EDIT) {
_blockShowEdit = true; // otherwise may jump on clicking outside the text element being edited
endEdit();
_blockShowEdit = false;
}
setCursor(QCursor(Qt::ArrowCursor));
break;
case ViewState::DRAG:

View file

@ -4921,8 +4921,6 @@ void MuseScore::undoRedo(bool undo)
cv->startUndoRedo(undo);
updateInputState(cs);
endCmd();
if (_inspector)
_inspector->update();
if (pianorollEditor)
pianorollEditor->update();
}
@ -5950,6 +5948,10 @@ void MuseScore::endCmd()
SelState ss = cs->selection().state();
selectionChanged(ss);
}
if (cv)
cv->moveViewportToLastEdit();
getAction("concert-pitch")->setChecked(cs->styleB(Sid::concertPitch));
if (e == 0 && cs->noteEntryMode())

View file

@ -71,6 +71,7 @@
#include "libmscore/slur.h"
#include "libmscore/spanner.h"
#include "libmscore/staff.h"
#include "libmscore/stafflines.h"
#include "libmscore/stafftext.h"
#include "libmscore/stafftype.h"
#include "libmscore/sticking.h"
@ -3240,7 +3241,7 @@ void ScoreView::adjustCanvasPosition(const Element* el, bool playBack, int staff
return;
QPointF p(el->canvasPos());
QRectF r(imatrix.mapRect(geometry()));
QRectF r(canvasViewport());
QRectF mRect(m->canvasBoundingRect());
QRectF sysRect;
if (staffIdx == -1)
@ -4801,4 +4802,88 @@ bool ScoreView::fotoMode() const
}
return false;
}
//---------------------------------------------------------
// needViewportMove
//---------------------------------------------------------
static bool needViewportMove(Score* cs, ScoreView* cv)
{
if (!cs || !cv)
return false;
const CmdState& state = cs->cmdState();
qDebug() << "asdf" << state.startTick() << state.endTick() << state.startStaff() << state.endStaff() << (state.element() ? state.element()->name() : "no_element");
if (state.startTick() < Fraction(0, 1))
return false;
const QRectF viewport = cv->canvasViewport(); // TODO: margins for intersection check?
const Element* editElement = state.element();
if (editElement && editElement->bbox().isValid())
return !viewport.intersects(editElement->canvasBoundingRect());
if (state.startTick().isZero() && state.endTick() == cs->endTick())
return false; // TODO: adjust staff perhaps?
// Is any part of the range visible?
Measure* mStart = cs->tick2measureMM(state.startTick());
Measure* mEnd = cs->tick2measureMM(state.endTick());
mEnd = mEnd ? mEnd->nextMeasureMM() : nullptr;
const int startStaff = state.startStaff() == -1 ? 0 : state.startStaff();
const int endStaff = state.endStaff() == -1 ? (cs->nstaves() - 1) : state.endStaff();
for (Measure* m = mStart; m && m != mEnd; m = m->nextMeasureMM()) {
for (int st = startStaff; st <= endStaff; ++st) {
const StaffLines* l = m->staffLines(st);
if (l) {
const QRectF r = l->bbox().translated(l->canvasPos());
// qDebug() << "viewport" << viewport << "lines" << l->canvasPos() << l->bbox() << p;
if (viewport.intersects(r))
return false;
}
}
}
// maybe viewport is at least near the desired position?
const QPointF p = viewport.center();
int staffIdx = 0;
const Measure* m = cs->pos2measure(p, &staffIdx, nullptr, nullptr, nullptr);
if (m && m->tick() >= state.startTick() && m->tick() <= state.endTick())
return false;
return true;
}
//---------------------------------------------------------
// moveViewportToLastEdit
//---------------------------------------------------------
void ScoreView::moveViewportToLastEdit()
{
if (_blockShowEdit)
return;
Score* s = score();
if (!needViewportMove(s, this))
return;
const CmdState& state = s->cmdState();
const Element* editElement = state.element();
const MeasureBase* mb = nullptr;
if (editElement)
mb = editElement->findMeasureBase();
if (!mb)
mb = s->tick2measureMM(state.startTick());
const Element* viewportElement = (editElement && editElement->bbox().isValid() && !mb->isMeasure()) ? editElement : mb;
const int staff = state.startStaff(); // TODO: choose the closest staff to the current viewport?
adjustCanvasPosition(viewportElement, /* playback */ false, staff);
}
}

View file

@ -143,6 +143,8 @@ class ScoreView : public QWidget, public MuseScoreView {
// it is inactive. Set this flag to true to change this behaviour.
bool _moveWhenInactive = false;
bool _blockShowEdit = false;
virtual void paintEvent(QPaintEvent*);
void paint(const QRect&, QPainter&);
@ -360,6 +362,8 @@ class ScoreView : public QWidget, public MuseScoreView {
QRectF toLogical(const QRectF& r) const { return imatrix.mapRect(r); }
QRect toPhysical(const QRectF& r) const { return _matrix.mapRect(r).toRect(); }
QRectF canvasViewport() const { return toLogical(geometry()); }
bool searchMeasure(int i);
bool searchPage(int i);
bool searchRehearsalMark(const QString& s);
@ -398,6 +402,8 @@ class ScoreView : public QWidget, public MuseScoreView {
virtual QCursor cursor() const { return QWidget::cursor(); }
void loopUpdate(bool val) { loopToggled(val); }
void moveViewportToLastEdit();
void updateShadowNotes();
OmrView* omrView() const { return _omrView; }