    //=============================================================================
    //  MuseScore
    //  Music Composition & Notation
    //
    //  Copyright (C) 2017 Werner Schweer & others
    //
    //  This program is free software; you can redistribute it and/or modify
    //  it under the terms of the GNU General Public License version 2
    //  as published by the Free Software Foundation and appearing in
    //  the file LICENCE.GPL
    //=============================================================================

    #include "scoreview.h"
    #include "magbox.h"
    #include "musescore.h"
    #include "seq.h"
    #include "texttools.h"
    #include "fotomode.h"
    #include "libmscore/score.h"
    #include "libmscore/keysig.h"
    #include "libmscore/segment.h"
    #include "libmscore/utils.h"
    #include "libmscore/text.h"
    #include "libmscore/measure.h"
    #include "libmscore/stafflines.h"
    #include "libmscore/chord.h"
    #include "libmscore/shadownote.h"

    namespace Ms {

    //---------------------------------------------------------
    //   event
    //---------------------------------------------------------

    bool ScoreView::event(QEvent* event)
          {
          if (event->type() == QEvent::KeyPress && editData.element) {
                QKeyEvent* ke = static_cast<QKeyEvent*>(event);
                if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
                      if (editData.element->isText())
                            return true;
                      bool rv = true;
                      if (ke->key() == Qt::Key_Tab) {
                            rv = editData.element->nextGrip(editData);
                            updateGrips();
                            _score->update();
                            if (rv)
                                  return true;
                            }
                      else if (ke->key() == Qt::Key_Backtab)
                            rv = editData.element->prevGrip(editData);
                      updateGrips();
                      _score->update();
                      if (rv)
                            return true;
                      }
                }
    //      else if (event->type() == CloneDrag) {
    //TODO:drag            Element* e = static_cast<CloneEvent*>(event)->element();
    //            cloneElement(e);
    //            }
          else if (event->type() == QEvent::Gesture) {
                return gestureEvent(static_cast<QGestureEvent*>(event));
                }
          else if (event->type() == QEvent::MouseButtonPress && qApp->focusWidget() != this) {
                QMouseEvent* me = static_cast<QMouseEvent*>(event);
                if (me->button() == Qt::LeftButton)
                      this->setFocus();
                }
          return QWidget::event(event);
          }

    //---------------------------------------------------------
    //   gestureEvent
    //    fired on touchscreen gestures as well as Mac touchpad gestures
    //---------------------------------------------------------

    bool ScoreView::gestureEvent(QGestureEvent *event)
          {
          if (QGesture *gesture = event->gesture(Qt::PinchGesture)) {
                // Zoom in/out when receiving a pinch gesture
                QPinchGesture *pinch = static_cast<QPinchGesture *>(gesture);

                static qreal magStart = 1.0;
                if (pinch->state() == Qt::GestureStarted) {
                      magStart = lmag();
                      }
                if (pinch->changeFlags() & QPinchGesture::ScaleFactorChanged) {
                      // On Windows, totalScaleFactor() contains the net magnification.
                      // On OS X, totalScaleFactor() is 1, and scaleFactor() contains the net magnification.
                      qreal value = pinch->totalScaleFactor();
                      if (value == 1) {
                            value = pinch->scaleFactor();
                            }
                      zoom(magStart*value, pinch->centerPoint());
                      }
                }
          return true;
          }

    //---------------------------------------------------------
    //   wheelEvent
    //---------------------------------------------------------

    void ScoreView::wheelEvent(QWheelEvent* event)
           {
    #define PIXELSSTEPSFACTOR 5

          QPoint pixelsScrolled = event->pixelDelta();
          QPoint stepsScrolled  = event->angleDelta();

          int dx = 0, dy = 0, n = 0;
          qreal nReal = 0.0;

          if (!pixelsScrolled.isNull()) {
                dx = pixelsScrolled.x();
                dy = pixelsScrolled.y();
                nReal = static_cast<qreal>(dy) / PIXELSSTEPSFACTOR;
                }
          else if (!stepsScrolled.isNull()) {
                dx = static_cast<qreal>(stepsScrolled.x()) * qMax(2, width() / 10) / 120;
                dy = static_cast<qreal>(stepsScrolled.y()) * qMax(2, height() / 10) / 120;
                nReal = static_cast<qreal>(stepsScrolled.y()) / 120;
                }

          n = (int) nReal;

          //this functionality seems currently blocked by the context menu
          if (event->buttons() & Qt::RightButton) {
                bool up = n > 0;
                if (!up)
                      n = -n;
                score()->startCmd();
                for (int i = 0; i < n; ++i)
                      score()->upDown(up, UpDownMode::CHROMATIC);
                score()->endCmd();
                return;
                }

          if (event->modifiers() & Qt::ControlModifier) { // Windows touch pad pinches also execute this
                QApplication::sendPostedEvents(this, 0);
                zoomStep(nReal, event->pos());
                return;
                }

          //make shift+scroll go horizontally
          if (event->modifiers() & Qt::ShiftModifier && dx == 0) {
                dx = dy;
                dy = 0;
                }

          if (dx == 0 && dy == 0)
                return;

          constraintCanvas(&dx, &dy);

          _matrix.setMatrix(_matrix.m11(), _matrix.m12(), _matrix.m13(), _matrix.m21(),
             _matrix.m22(), _matrix.m23(), _matrix.dx()+dx, _matrix.dy()+dy, _matrix.m33());
          imatrix = _matrix.inverted();

          scroll(dx, dy, QRect(0, 0, width(), height()));
          emit viewRectChanged();
          emit offsetChanged(_matrix.dx(), _matrix.dy());
          }

    //---------------------------------------------------------
    //   resizeEvent
    //---------------------------------------------------------

    void ScoreView::resizeEvent(QResizeEvent* /*ev*/)
          {
          if (_magIdx != MagIdx::MAG_FREE)
                setMag(mscore->getMag(this));
          emit sizeChanged();
          }

    //---------------------------------------------------------
    //   focusInEvent
    //---------------------------------------------------------

    void ScoreView::focusInEvent(QFocusEvent* event)
          {
          if (this != mscore->currentScoreView())
             mscore->setCurrentScoreView(this);

          if (mscore->splitScreen()) {
                if (!focusFrame) {
                      focusFrame = new QFocusFrame;
                      QPalette p(focusFrame->palette());
                      p.setColor(QPalette::WindowText, Qt::blue);
                      focusFrame->setPalette(p);
                      }
                focusFrame->setWidget(static_cast<QWidget*>(this));
                }
          QWidget::focusInEvent(event);
          }

    //---------------------------------------------------------
    //   focusOutEvent
    //---------------------------------------------------------

    void ScoreView::focusOutEvent(QFocusEvent* event)
          {
          if (focusFrame)
                focusFrame->setWidget(0);
          QWidget::focusOutEvent(event);
          }

    //---------------------------------------------------------
    //   mouseReleaseEvent
    //---------------------------------------------------------

    void ScoreView::mouseReleaseEvent(QMouseEvent*)
          {
          editData.buttons = Qt::NoButton;
          if (seq)
                seq->stopNoteTimer();
          switch (state) {
                case ViewState::DRAG:
                case ViewState::DRAG_OBJECT:
                case ViewState::LASSO:
                      changeState(ViewState::NORMAL);
                      break;
                case ViewState::DRAG_EDIT:
                      changeState(ViewState::EDIT);
                      break;
                case ViewState::FOTO_DRAG:
                case ViewState::FOTO_DRAG_EDIT:
                case ViewState::FOTO_DRAG_OBJECT:
                      changeState(ViewState::FOTO);
                      break;
                case ViewState::NORMAL:
                case ViewState::EDIT:
                case ViewState::NOTE_ENTRY:
                case ViewState::PLAY:
                case ViewState::ENTRY_PLAY:
                case ViewState::FOTO:
                case ViewState::FOTO_LASSO:
                      break;
                }
          }

    //---------------------------------------------------------
    //   mousePressEventNormal
    //    handle mouse press event for NORMAL mode
    //---------------------------------------------------------

    void ScoreView::mousePressEventNormal(QMouseEvent* ev)
          {
          _score->masterScore()->cmdState().reset();      // DEBUG: should not be necessary

          Qt::KeyboardModifiers keyState = ev->modifiers();
          SelectType st = SelectType::SINGLE;
          if (keyState == Qt::NoModifier)
                st = SelectType::SINGLE;
          else if (keyState & Qt::ShiftModifier)
                st = SelectType::RANGE;
          else if (keyState & Qt::ControlModifier)
                st = SelectType::ADD;

          Element* e = editData.element;
          if (e) {
                if (keyState == (Qt::ShiftModifier | Qt::ControlModifier)) {
                      cloneElement(e);
                      return;
                      }
                if (e->isKeySig() && (keyState != Qt::ControlModifier) && st == SelectType::SINGLE) {
                      // special case: select for all staves
                      Segment* s = toKeySig(e)->segment();
                      bool first = true;
                      for (int staffIdx = 0; staffIdx < _score->nstaves(); ++staffIdx) {
                            Element* e = s->element(staffIdx * VOICES);
                            if (e) {
                                  e->score()->select(e, first ? SelectType::SINGLE : SelectType::ADD);
                                  first = false;
                                  }
                            }
                      }
                else {
                      if (st == SelectType::ADD && e->selected())
                            e->score()->deselect(e);
                      else
                            e->score()->select(e, st, -1);
                      }
                if (e->isNote())
                      mscore->play(e);
                if (e) {
                      _score = e->score();
                      _score->setUpdateAll();
                      }
                }
          else {
                // special case: chacke if measure is selected
                int staffIdx;
                Measure* m = _score->pos2measure(editData.startMove, &staffIdx, 0, 0, 0);
                if (m && m->staffLines(staffIdx)->canvasBoundingRect().contains(editData.startMove)) {
                      _score->select(m, st, staffIdx);
                      _score->setUpdateAll();
                      }
                else
                      _score->deselectAll();
                }
          _score->update();
          mscore->endCmd();
          }

    //---------------------------------------------------------
    //   mousePressEvent
    //---------------------------------------------------------

    void ScoreView::mousePressEvent(QMouseEvent* ev)
          {
          editData.startMovePixel = ev->pos();
          editData.startMove = toLogical(ev->pos());
          editData.lastPos   = editData.startMove;
          editData.pos       = editData.startMove;
          editData.buttons   = ev->buttons();
          editData.modifiers = qApp->keyboardModifiers();

          Element* e         = elementNear(editData.startMove);
          qDebug("element %s", e ? e->name() : "--");

          switch (state) {
                case ViewState::NORMAL:
                      if (ev->button() == Qt::RightButton)   // context menu?
                            break;
                      editData.element = e;
                      mousePressEventNormal(ev);
                      break;

                case ViewState::FOTO: {
                      if (ev->buttons() & Qt::RightButton)
                            break;
                      editData.element = _foto;
                      bool gripClicked = false;
                      qreal a = editData.grip[0].width() * 1.0;
                      for (int i = 0; i < editData.grips; ++i) {
                            if (editData.grip[i].adjusted(-a, -a, a, a).contains(editData.startMove)) {
                                  editData.curGrip = Grip(i);
                                  updateGrips();
                                  gripClicked = true;
                                  score()->update();
                                  break;
                                  }
                            }
                      if (gripClicked)
                            changeState(ViewState::FOTO_DRAG_EDIT);
                      else if (_foto->canvasBoundingRect().contains(editData.startMove))
                            changeState(ViewState::FOTO_DRAG_OBJECT);
                      else
                            changeState(ViewState::FOTO_DRAG);
                      }
                      break;

                case ViewState::NOTE_ENTRY:
                      _score->startCmd();
                      _score->putNote(editData.startMove, ev->modifiers() & Qt::ShiftModifier, ev->modifiers() & Qt::ControlModifier);
                      _score->endCmd();
                      if (_score->inputState().cr())
                            adjustCanvasPosition(_score->inputState().cr(), false);
                      break;

                case ViewState::EDIT: {
                      if (editData.grips) {
                            qreal a = editData.grip[0].width() * 1.0;
                            for (int i = 0; i < editData.grips; ++i) {
                                  if (editData.grip[i].adjusted(-a, -a, a, a).contains(editData.startMove)) {
                                        editData.curGrip = Grip(i);
                                        updateGrips();
                                        score()->update();
                                        break;
                                        }
                                  }
                            }
                      else {
                            if (!editData.element->canvasBoundingRect().contains(editData.startMove)) {
                                  editData.element = e;
                                  changeState(ViewState::NORMAL);
                                  mousePressEventNormal(ev);
                                  }
                            else {
                                  editData.element->mousePress(editData);
                                  score()->update();
                                  }
                            }
                      }
                      break;

                default:
                      qDebug("mousePressEvent in state %d", int(state));
                      break;
                }
          }

    //---------------------------------------------------------
    //   mouseMoveEvent
    //---------------------------------------------------------

    void ScoreView::mouseMoveEvent(QMouseEvent* me)
          {
          if (state != ViewState::NOTE_ENTRY && editData.buttons == Qt::NoButton)
                return;

          // start some drag operations after a minimum of movement:
          bool drag = (me->pos() - editData.startMovePixel).manhattanLength() > 4;

          switch (state) {
                case ViewState::NORMAL:
                      if (!editData.element && (me->modifiers() & Qt::ShiftModifier))
                            changeState(ViewState::LASSO);
                      else if (editData.element && !(me->modifiers())) {
                            if (!drag)
                                  return;
                            changeState(ViewState::DRAG_OBJECT);
                            }
                      else
                            changeState(ViewState::DRAG);
                      break;

                case ViewState::NOTE_ENTRY: {
                      QPointF p = toLogical(me->pos());
                      QRectF r(shadowNote->canvasBoundingRect());
                      setShadowNote(p);
                      r |= shadowNote->canvasBoundingRect();
                      update(toPhysical(r).adjusted(-2, -2, 2, 2));
                      }
                      break;

                case ViewState::DRAG:
                case ViewState::FOTO_DRAG:
                      dragScoreView(me);
                      break;

                case ViewState::DRAG_OBJECT:
                case ViewState::FOTO_DRAG_OBJECT:
                      doDragElement(me);
                      break;

                case ViewState::DRAG_EDIT:
                case ViewState::FOTO_DRAG_EDIT:
                      doDragEdit(me);
                      break;

                case ViewState::LASSO:
                      doDragLasso(me);
                      break;

                case ViewState::EDIT:
                      if (!drag)
                            return;
                      score()->startCmd();
                      editData.element->startEditDrag(editData);
                      changeState(ViewState::DRAG_EDIT);
                      break;

                default:
                      break;
                }
          update();
          }

    //---------------------------------------------------------
    //   mouseDoubleClickEvent
    //---------------------------------------------------------

    void ScoreView::mouseDoubleClickEvent(QMouseEvent* me)
          {
          if (state == ViewState::NORMAL) {
                QPointF p = toLogical(me->pos());
                Element* e = elementNear(p);
                if (e && e->isEditable()) {
                      startEditMode(e);
                      changeState(ViewState::EDIT);
                      }
                }
          }

    //---------------------------------------------------------
    //   CmdContext
    //---------------------------------------------------------

    struct CmdContext {
          Score* s;
          CmdContext(Score* _s) : s(_s) { s->startCmd(); }
          ~CmdContext()                 { s->endCmd();   }
          };

    //---------------------------------------------------------
    //   keyPressEvent
    //---------------------------------------------------------

    void ScoreView::keyPressEvent(QKeyEvent* ev)
          {
          if (state != ViewState::EDIT)
                return;
          CmdContext cmdContext(_score);
          editData.key       = ev->key();
          editData.modifiers = ev->modifiers();
          editData.s         = ev->text();

          if (MScore::debugMode)
                qDebug("keyPressEvent key 0x%02x(%c) mod 0x%04x <%s> nativeKey 0x%02x scancode %d",
                   editData.key, editData.key, int(editData.modifiers), qPrintable(editData.s), ev->nativeVirtualKey(), ev->nativeScanCode());

          if (editData.element->isLyrics()) {
                if (editKeyLyrics(ev))
                      return;
                }
          else if (editData.element->isHarmony()) {
                if (editData.key == Qt::Key_Space && !(editData.modifiers & CONTROL_MODIFIER)) {
                      harmonyBeatsTab(true, editData.modifiers & Qt::ShiftModifier);
                      return;
                      }
                }
          else if (editData.element->isFiguredBass()) {
                if (editData.key == Qt::Key_Space && !(editData.modifiers & CONTROL_MODIFIER)) {
                      figuredBassTab(false, editData.modifiers & Qt::ShiftModifier);
                      return;
                      }
                }

    #ifdef Q_OS_WIN // Japenese IME on Windows needs to know when Contrl/Alt/Shift/CapsLock is pressed while in predit
          if (editData.element->isText()) {
                Text* text = toText(editData.element);
                if (text->cursor(editData)->format()->preedit() && QGuiApplication::inputMethod()->locale().script() == QLocale::JapaneseScript &&
                    ((editData.key == Qt::Key_Control || (editData.modifiers & Qt::ControlModifier)) ||
                     (editData.key == Qt::Key_Alt     || (editData.modifiers & Qt::AltModifier)) ||
                     (editData.key == Qt::Key_Shift   || (editData.modifiers & Qt::ShiftModifier)) ||
                     (editData.key == Qt::Key_CapsLock))) {
                      return; // musescore will ignore this key event so that the IME can handle it
                      }
                }
    #endif

          if (!( (editData.modifiers & Qt::ShiftModifier) && (editData.key == Qt::Key_Backtab) )) {
                if (editData.element->edit(editData)) {
                      if (editData.element->isText())
                            mscore->textTools()->updateTools(editData);
                      else
                            updateGrips();
                      return;
                      }
                }

          QPointF delta;
          qreal _spatium = editData.element->spatium();

          qreal xval, yval;
          if (editData.element->isBeam()) {
                xval = 0.25 * _spatium;
                if (editData.modifiers & Qt::ControlModifier)
                      xval = _spatium;
                else if (editData.modifiers & Qt::AltModifier)
                      xval = 4 * _spatium;
                }
          else {
                xval = MScore::nudgeStep * _spatium;
                if (editData.modifiers & Qt::ControlModifier)
                      xval = MScore::nudgeStep10 * _spatium;
                else if (editData.modifiers & Qt::AltModifier)
                      xval = MScore::nudgeStep50 * _spatium;
                }
          yval = xval;

          if (mscore->vRaster()) {
                qreal vRaster = _spatium / MScore::vRaster();
                if (yval < vRaster)
                      yval = vRaster;
                }
          if (mscore->hRaster()) {
                qreal hRaster = _spatium / MScore::hRaster();
                if (xval < hRaster)
                      xval = hRaster;
                }
          // TODO: if raster, then xval/yval should be multiple of raster

          switch (editData.key) {
                case Qt::Key_Left:
                      delta = QPointF(-xval, 0);
                      break;
                case Qt::Key_Right:
                      delta = QPointF(xval, 0);
                      break;
                case Qt::Key_Up:
                      delta = QPointF(0, -yval);
                      break;
                case Qt::Key_Down:
                      delta = QPointF(0, yval);
                      break;
                default:
                      ev->ignore();
                      return;
                }
          editData.delta   = delta;
          editData.hRaster = mscore->hRaster();
          editData.vRaster = mscore->vRaster();
          if (editData.curGrip != Grip::NO_GRIP && int(editData.curGrip) < editData.grips)
                editData.pos = editData.grip[int(editData.curGrip)].center() + delta;
          editData.element->startEditDrag(editData);
          editData.element->editDrag(editData);
          editData.element->endEditDrag(editData);
          updateGrips();
          }

    //---------------------------------------------------------
    //   keyReleaseEvent
    //---------------------------------------------------------

    void ScoreView::keyReleaseEvent(QKeyEvent* ev)
          {
          if (state == ViewState::EDIT) {
                auto modifiers = Qt::ControlModifier | Qt::ShiftModifier;
                if (editData.element->isText() && ((ev->modifiers() & modifiers) == 0)) {
                      Text* text = toText(editData.element);
                      text->endHexState();
                      ev->accept();
                      update();
                      }
                }
          }

    //---------------------------------------------------------
    //   contextPopup
    //---------------------------------------------------------

    void ScoreView::contextMenuEvent(QContextMenuEvent* ev)
          {
          if (state == ViewState::FOTO) {
                fotoContextPopup(ev);
                return;
                }
          QPoint gp          = ev->globalPos();
          editData.startMove = toLogical(ev->pos());
          Element* e         = elementNear(editData.startMove);
          if (e) {
                if (!e->selected()) {
                      // bool control = (ev->modifiers() & Qt::ControlModifier) ? true : false;
                      // _score->select(e, control ? SelectType::ADD : SelectType::SINGLE, 0);
                      // editData.element = e;
                      // select(ev);
                      }
                if (seq)
                      seq->stopNotes();       // stop now because we dont get a mouseRelease event
                objectPopup(gp, e);
                }
          else {
                int staffIdx;
                Measure* m = _score->pos2measure(editData.startMove, &staffIdx, 0, 0, 0);
                if (m && m->staffLines(staffIdx)->canvasBoundingRect().contains(editData.startMove))
                      measurePopup(gp, m);
                else {
                      QMenu* popup = new QMenu();
                      popup->addAction(getAction("edit-style"));
                      popup->addAction(getAction("page-settings"));
                      popup->addAction(getAction("load-style"));
                      _score->update();
                      popup->popup(gp);
                      }
                }
          ev->accept();
          }

    //---------------------------------------------------------
    //   escapeCmd
    //---------------------------------------------------------

    void ScoreView::escapeCmd()
          {
          switch (state) {
                case ViewState::EDIT:
                      changeState(ViewState::NORMAL);
                      break;
                case ViewState::FOTO:
                case ViewState::NOTE_ENTRY:
                case ViewState::PLAY:
                      changeState(ViewState::NORMAL);
                      break;
                case ViewState::NORMAL:
                      _score->deselectAll();
                      update();
                      break;
                default:
                      break;
                }
          }

    //---------------------------------------------------------
    //   stateName
    //---------------------------------------------------------

    static const char* stateName(ViewState s)
          {
          const char* p;
          switch (s) {
                case ViewState::NORMAL:             p = "NORMAL";           break;
                case ViewState::DRAG:               p = "DRAG";             break;
                case ViewState::DRAG_OBJECT:        p = "DRAG_OBJECT";      break;
                case ViewState::EDIT:               p = "EDIT";             break;
                case ViewState::DRAG_EDIT:          p = "DRAG_EDIT";        break;
                case ViewState::LASSO:              p = "LASSO";            break;
                case ViewState::NOTE_ENTRY:         p = "NOTE_ENTRY";       break;
                case ViewState::PLAY:               p = "PLAY";             break;
                case ViewState::ENTRY_PLAY:         p = "ENTRY_PLAY";       break;
                case ViewState::FOTO:               p = "FOTO";             break;
                case ViewState::FOTO_DRAG:          p = "FOTO_DRAG";        break;
                case ViewState::FOTO_DRAG_EDIT:     p = "FOTO_DRAG_EDIT";   break;
                case ViewState::FOTO_DRAG_OBJECT:   p = "FOTO_DRAG_OBJECT"; break;
                case ViewState::FOTO_LASSO:         p = "FOTO_LASSO";       break;
                }
          return p;
          }

    //---------------------------------------------------------
    //   seqStopped
    //---------------------------------------------------------

    void ScoreView::seqStopped()
          {
          changeState(ViewState::NORMAL);
          }

    //---------------------------------------------------------
    //   changeState
    //---------------------------------------------------------

    void ScoreView::changeState(ViewState s)
          {
          qDebug("changeState %s  -> %s", stateName(state), stateName(s));

    //      if (state == ViewState::EDIT && s == ViewState::EDIT) {
    //            startEdit();
    //            return;
    //            }
          if (s == ViewState::PLAY && !seq)
                return;
          if (s == state)
                return;
          //
          //    end current state
          //
          switch (state) {
                case ViewState::NOTE_ENTRY:
                      endNoteEntry();
                      break;
                case ViewState::DRAG:
                      break;
                case ViewState::DRAG_OBJECT:
                case ViewState::FOTO_DRAG_OBJECT:
                      endDrag();
                      break;
                case ViewState::FOTO_DRAG_EDIT:
                case ViewState::DRAG_EDIT:
                      endDragEdit();
                      break;
                case ViewState::FOTO:
                      if (s != ViewState::FOTO_DRAG && s != ViewState::FOTO_DRAG_EDIT && s != ViewState::FOTO_DRAG_OBJECT)
                            stopFotomode();
                      break;
                case ViewState::LASSO:
                      endLasso();
                      break;
                case ViewState::PLAY:
                      seq->stop();
                      break;
                default:
                      break;
                }
          //
          //    start new state
          //
          switch (s) {
                case ViewState::NORMAL:
                      if (state == ViewState::EDIT)
                            endEdit();
                      setCursor(QCursor(Qt::ArrowCursor));
                      break;
                case ViewState::DRAG:
                      setCursor(QCursor(Qt::SizeAllCursor));
                      break;
                case ViewState::FOTO_DRAG_OBJECT:
                      _score->select(_foto);
                      // fall through
                case ViewState::DRAG_OBJECT:
                      setCursor(QCursor(Qt::ArrowCursor));
                      startDrag();
                      break;
                case ViewState::FOTO_DRAG:
                      setCursor(QCursor(Qt::SizeAllCursor));
                      break;
                case ViewState::NOTE_ENTRY:
                      setCursor(QCursor(Qt::ArrowCursor));
                      startNoteEntry();
                      break;
                case ViewState::DRAG_EDIT:
                case ViewState::FOTO_DRAG_EDIT:
                      setCursor(QCursor(Qt::ArrowCursor));
                      break;
                case ViewState::FOTO:
                      setCursor(QCursor(Qt::ArrowCursor));
                      if (state != ViewState::FOTO_DRAG && state != ViewState::FOTO_DRAG_EDIT && state != ViewState::FOTO_DRAG_OBJECT)
                            startFotomode();
                      if (state == ViewState::FOTO_DRAG_OBJECT)
                            startEdit();
                      break;
                case ViewState::EDIT:
                      if (state != ViewState::DRAG_EDIT)
                            startEdit();
                      break;
                case ViewState::LASSO:
                      break;
                case ViewState::PLAY:
                      seq->start();
                      break;
                case ViewState::ENTRY_PLAY:
                case ViewState::FOTO_LASSO:
                      break;
                }

          state = s;
          mscore->changeState(mscoreState());
          }

    }    // namespace Ms

↑ V547 Expression 'e' is always true.