    //=============================================================================
    //  MuseScore
    //  Music Composition & Notation
    //
    //  Copyright (C) 2013 Werner Schweer and 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 LICENSE.GPL
    //=============================================================================

    #include "exampleview.h"
    #include "preferences.h"
    #include "libmscore/score.h"
    #include "libmscore/element.h"
    #include "libmscore/page.h"
    #include "libmscore/system.h"
    #include "libmscore/icon.h"
    #include "libmscore/chord.h"
    #include "libmscore/xml.h"

    namespace Ms {

    //---------------------------------------------------------
    //   ExampleView
    //---------------------------------------------------------

    ExampleView::ExampleView(QWidget* parent)
       : QFrame(parent)
          {
          _score = 0;
          setAcceptDrops(true);
          setFocusPolicy(Qt::StrongFocus);
          resetMatrix();
          _fgPixmap = nullptr;
          if (preferences.fgUseColor)
                _fgColor = preferences.fgColor;
          else {
                _fgPixmap = new QPixmap(preferences.fgWallpaper);
                if (_fgPixmap == 0 || _fgPixmap->isNull())
                      qDebug("no valid pixmap %s", qPrintable(preferences.fgWallpaper));
                }
          // setup drag canvas state
          sm          = new QStateMachine(this);
          QState* stateActive = new QState;

          QState* s1 = new QState(stateActive);
          s1->setObjectName("example-normal");
          s1->assignProperty(this, "cursor", QCursor(Qt::ArrowCursor));

          QState* s = new QState(stateActive);
          s->setObjectName("example-drag");
          s->assignProperty(this, "cursor", QCursor(Qt::SizeAllCursor));
          QEventTransition* cl = new QEventTransition(this, QEvent::MouseButtonRelease);
          cl->setTargetState(s1);
          s->addTransition(cl);
          s1->addTransition(new DragTransitionExampleView(this));

          sm->addState(stateActive);
          stateActive->setInitialState(s1);
          sm->setInitialState(stateActive);

          sm->start();
          }

    //---------------------------------------------------------
    //   ~ExampleView
    //---------------------------------------------------------

    ExampleView::~ExampleView()
          {
          if (_fgPixmap)
                delete _fgPixmap;
          }

    //---------------------------------------------------------
    //   resetMatrix
    //    used to reset scrolling in case time signature num or denom changed
    //---------------------------------------------------------

    void ExampleView::resetMatrix()
          {
          double mag = 0.9 * guiScaling * (DPI_DISPLAY / DPI);  // 90% of nominal
          qreal _spatium = SPATIUM20 * mag;
          // example would normally be 10sp from top of page; this leaves 3sp margin above
    //      _matrix  = QTransform(mag, 0.0, 0.0, mag, _spatium, -_spatium * 7.0);
          _matrix  = QTransform(mag, 0.0, 0.0, mag, _spatium, -_spatium * 10.0);
          imatrix  = _matrix.inverted();
          }

    void ExampleView::layoutChanged()
          {
          }

    void ExampleView::dataChanged(const QRectF&)
          {
          }

    void ExampleView::updateAll()
          {
          update();
          }

    void ExampleView::adjustCanvasPosition(const Element* /*el*/, bool /*playBack*/)
          {
          }

    //---------------------------------------------------------
    //   setScore
    //---------------------------------------------------------

    void ExampleView::setScore(Score* s)
          {
          delete _score;
          _score = s;
          _score->addViewer(this);
          _score->setLayoutMode(LayoutMode::LINE);
          _score->doLayout();
          update();
          }

    void ExampleView::removeScore()
          {
          }

    void ExampleView::changeEditElement(Element*)
          {
          }

    QCursor ExampleView::cursor() const
          {
          return QCursor();
          }

    void ExampleView::setCursor(const QCursor&)
          {
          }

    int ExampleView::gripCount() const
          {
          return 0;
          }

    void ExampleView::setDropRectangle(const QRectF&)
          {
          }

    void ExampleView::cmdAddSlur(Note* /*firstNote*/, Note* /*lastNote*/)
          {
          }

    void ExampleView::startEdit()
          {
          }

    void ExampleView::startEdit(Element*, Grip /*startGrip*/)
          {
          }

    Element* ExampleView::elementNear(QPointF)
          {
          return 0;
          }

    void ExampleView::drawBackground(QPainter* p, const QRectF& r) const
          {
          if (_fgPixmap == 0 || _fgPixmap->isNull())
                p->fillRect(r, _fgColor);
          else {
                p->drawTiledPixmap(r, *_fgPixmap, r.topLeft()
                   - QPoint(lrint(_matrix.dx()), lrint(_matrix.dy())));
                }
          }

    //---------------------------------------------------------
    //   drawElements
    //---------------------------------------------------------

    void ExampleView::drawElements(QPainter& painter, const QList<Element*>& el)
          {
          for (Element* e : el) {
                e->itemDiscovered = 0;
                QPointF pos(e->pagePos());
                painter.translate(pos);
                e->draw(&painter);
                painter.translate(-pos);
                }
          }

    //---------------------------------------------------------
    //   paintEvent
    //---------------------------------------------------------

    void ExampleView::paintEvent(QPaintEvent* ev)
          {
          if (_score) {
                QPainter p(this);
                p.setRenderHint(QPainter::Antialiasing, preferences.antialiasedDrawing);
                p.setRenderHint(QPainter::TextAntialiasing, true);
                const QRect r(ev->rect());

                drawBackground(&p, r);

                p.setTransform(_matrix);
                QRectF fr = imatrix.mapRect(QRectF(r));

                QRegion r1(r);
                Page* page = _score->pages().front();
                QList<Element*> ell = page->items(fr);
                qStableSort(ell.begin(), ell.end(), elementLessThan);
                drawElements(p, ell);
                }
          QFrame::paintEvent(ev);
          }

    //---------------------------------------------------------
    //   dragEnterEvent
    //---------------------------------------------------------

    void ExampleView::dragEnterEvent(QDragEnterEvent* event)
          {
          const QMimeData* data = event->mimeData();
          if (data->hasFormat(mimeSymbolFormat)) {
                event->acceptProposedAction();

                QByteArray a = data->data(mimeSymbolFormat);

    // qDebug("ExampleView::dragEnterEvent Symbol: <%s>", a.data());

                XmlReader e(score(), a);
                QPointF dragOffset;
                Fraction duration;  // dummy
                ElementType type = Element::readType(e, &dragOffset, &duration);

                dragElement = Element::create(type, _score);
                if (dragElement) {
                      dragElement->setParent(0);
                      dragElement->read(e);
                      dragElement->layout();
                      }
                return;
                }
          }

    //---------------------------------------------------------
    //   dragLeaveEvent
    //---------------------------------------------------------

    void ExampleView::dragLeaveEvent(QDragLeaveEvent*)
          {
          if (dragElement) {
                delete dragElement;
                dragElement = 0;
                }
          setDropTarget(0);
          }

    //---------------------------------------------------------
    //   moveElement
    //---------------------------------------------------------

    static void moveElement(void* data, Element* e)
          {
          QPointF* pos = (QPointF*)data;
          e->score()->addRefresh(e->canvasBoundingRect());
          e->setPos(*pos);
          e->score()->addRefresh(e->canvasBoundingRect());
          }

    //---------------------------------------------------------
    //   dragMoveEvent
    //---------------------------------------------------------

    void ExampleView::dragMoveEvent(QDragMoveEvent* event)
          {
          event->acceptProposedAction();

          if (!dragElement || dragElement->type() != ElementType::ICON)
                return;

          QPointF pos(imatrix.map(QPointF(event->pos())));
          QList<Element*> el = elementsAt(pos);
          bool found = false;
          foreach(const Element* e, el) {
                if (e->type() == ElementType::NOTE) {
                      setDropTarget(const_cast<Element*>(e));
                      found = true;
                      break;
                      }
                }
          if (!found)
                setDropTarget(0);
          dragElement->scanElements(&pos, moveElement, false);
          _score->update();
          return;
          }

    //---------------------------------------------------------
    //   setDropTarget
    //---------------------------------------------------------

    void ExampleView::setDropTarget(const Element* el)
          {
          if (dropTarget != el) {
                if (dropTarget) {
                      dropTarget->setDropTarget(false);
                      dropTarget = 0;
                      }
                dropTarget = el;
                if (dropTarget) {
                      dropTarget->setDropTarget(true);
                      }
                }
          if (!dropAnchor.isNull()) {
                QRectF r;
                r.setTopLeft(dropAnchor.p1());
                r.setBottomRight(dropAnchor.p2());
                dropAnchor = QLineF();
                }
          if (dropRectangle.isValid()) {
                dropRectangle = QRectF();
                }
          update();
          }

    //---------------------------------------------------------
    //   dropEvent
    //---------------------------------------------------------

    void ExampleView::dropEvent(QDropEvent* event)
          {
          QPointF pos(imatrix.map(QPointF(event->pos())));

          if (!dragElement)
               return;
          if (dragElement->type() != ElementType::ICON) {
                delete dragElement;
                dragElement = 0;
                return;
                }
          foreach (Element* e, elementsAt(pos)) {
                if (e->type() == ElementType::NOTE) {
                      Icon* icon = static_cast<Icon*>(dragElement);
                      Chord* chord = static_cast<Note*>(e)->chord();
                      emit beamPropertyDropped(chord, icon);
                      switch (icon->iconType()) {
                            case IconType::SBEAM:
                                  chord->setBeamMode(Beam::Mode::BEGIN);
                                  break;
                            case IconType::MBEAM:
                                  chord->setBeamMode(Beam::Mode::AUTO);
                                  break;
                            case IconType::BEAM32:
                                  chord->setBeamMode(Beam::Mode::BEGIN32);
                                  break;
                            case IconType::BEAM64:
                                  chord->setBeamMode(Beam::Mode::BEGIN64);
                                  break;
                            default:
                                  break;
                            }
                      score()->doLayout();
                      break;
                      }
                }
          event->acceptProposedAction();
          delete dragElement;
          dragElement = 0;
          setDropTarget(0);
          }

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

    void ExampleView::mousePressEvent(QMouseEvent* event)
          {
          startMove  = imatrix.map(QPointF(event->pos()));
          QPointF pos(imatrix.map(QPointF(event->pos())));

          foreach (Element* e, elementsAt(pos)) {
                if (e->type() == ElementType::NOTE) {
                      emit noteClicked(static_cast<Note*>(e));
                      break;
                      }
                }
          }

    //---------------------------------------------------------
    //   sizeHint
    //---------------------------------------------------------

    QSize ExampleView::sizeHint() const
          {
          qreal mag = 0.9 * guiScaling * (DPI_DISPLAY / DPI);
          qreal _spatium = SPATIUM20 * mag;
          // staff is 4sp tall with 3sp margin above; this leaves 3sp margin below
          qreal height = 10.0 * _spatium;
          if (score() && score()->pages().size() > 0)
                height = score()->pages()[0]->tbbox().height() * mag + (6 * _spatium);
          return QSize(1000 * mag, height);
          }

    //---------------------------------------------------------
    //   dragExampleView
    //     constrained scrolling ensuring that this ExampleView won't be moved past the borders of its QFrame
    //---------------------------------------------------------

    void ExampleView::dragExampleView(QMouseEvent* ev)
          {
          QPoint d = ev->pos() - _matrix.map(startMove).toPoint();
          int dx   = d.x();
          if (dx == 0)
                return;

          constraintCanvas(&dx);

          // Perform the actual scrolling
          _matrix.setMatrix(_matrix.m11(), _matrix.m12(), _matrix.m13(), _matrix.m21(),
             _matrix.m22(), _matrix.m23(), _matrix.dx()+dx, _matrix.dy(), _matrix.m33());
          imatrix = _matrix.inverted();
          scroll(dx, 0);
          }

    void DragTransitionExampleView::onTransition(QEvent* e)
          {
          QStateMachine::WrappedEvent* we = static_cast<QStateMachine::WrappedEvent*>(e);
          QMouseEvent* me = static_cast<QMouseEvent*>(we->event());
          canvas->dragExampleView(me);
          }

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

    void ExampleView::wheelEvent(QWheelEvent* event)
           {
          QPoint pixelsScrolled = event->pixelDelta();
          QPoint stepsScrolled = event->angleDelta();
          int dx = 0, dy = 0;
          if (!pixelsScrolled.isNull()) {
                dx = pixelsScrolled.x();
                dy = pixelsScrolled.y();
                }
          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;
                }

          if (dx == 0) {
                if (dy == 0)
                      return;
                else
                      dx = dy;
                }

          constraintCanvas(&dx);

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

    //-----------------------------------------------------------------------------
    //   constraintCanvas
    //-----------------------------------------------------------------------------

    void ExampleView::constraintCanvas (int* dxx)
          {
          int dx = *dxx;

          Q_ASSERT(_score->pages().front()->system(0)); // should exist if doLayout ran

          // form rectangle bounding the the system with a spatium margin and translate relative to view space
          qreal xstart = _score->pages().front()->system(0)->bbox().left() - SPATIUM20;
          qreal xend = _score->pages().front()->system(0)->bbox().right() + 2.0 * SPATIUM20;
          QRectF systemScaledViewRect(xstart * _matrix.m11(), 0, xend * _matrix.m11(), 0);
          systemScaledViewRect.translate(_matrix.dx(), 0);

          qreal frameWidth = static_cast<QFrame*>(this)->frameRect().width();

          // constrain the dx of scrolling so that this ExampleView won't be moved past the borders of its QFrame
          if (dx > 0) {
                // when moving right, ensure the left edge of systemScaledViewRect won't be right of frame's left edge
                if (systemScaledViewRect.left() + dx > 0)
                      dx = -systemScaledViewRect.left();
                }
          else {
                // never move left if entire system already fits entirely within the frame
                if (systemScaledViewRect.width() < frameWidth)
                      dx = 0;
                // when moving left, ensure the right edge of systemScaledViewRect won't be left of frame's right edge
                else if (systemScaledViewRect.right() + dx < frameWidth)
                            dx = frameWidth - systemScaledViewRect.right();
                }

          *dxx = dx;
          }
    }

↑ V668 There is no sense in testing the '_fgPixmap' pointer against null, as the memory was allocated using the 'new' operator. The exception will be generated in the case of memory allocation error.