Move ScoreView's viewport to show the last score changes
This commit is contained in:
parent
51e8517543
commit
7dc8ca53b9
4 changed files with 100 additions and 4 deletions
|
@ -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:
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in a new issue