    //=============================================================================
    //  MuseScore
    //  Music Composition & Notation
    //
    //  Copyright (C) 2002-2012 Werner Schweer
    //
    //  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 "chordview.h"
    #include "piano.h"
    #include "libmscore/chord.h"
    #include "libmscore/note.h"
    #include "libmscore/noteevent.h"
    #include "preferences.h"
    #include "musescore.h"
    #include "libmscore/mscore.h"
    #include "libmscore/score.h"

    namespace Ms {

    static const int CHORD_MAP_OFFSET = 50;
    static const int grip = 7;

    //---------------------------------------------------------
    //   GripItem
    //---------------------------------------------------------

    GripItem::GripItem(int type, ChordView* v)
       : QGraphicsRectItem()
          {
          _gripType = type;
          _view     = v;
          setFlags(flags() | ItemIsSelectable | ItemIsFocusable
             | ItemIgnoresTransformations | ItemIsMovable);
          setRect(-grip, -grip, grip*2, grip*2);
          setPos(0, 0);
          _event = 0;
          }

    //---------------------------------------------------------
    //   paint
    //---------------------------------------------------------

    void GripItem::paint(QPainter* p, const QStyleOptionGraphicsItem*, QWidget*)
          {
          QPen pen(MScore::defaultColor);
          pen.setWidthF(2.0);
          p->setPen(pen);
          p->setBrush(isSelected() ? QBrush(Qt::blue) : Qt::NoBrush);
          p->drawRect(-grip, -grip, grip*2, grip*2);
          }

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

    void GripItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
          {
          QPointF np = mapToScene(event->pos());
          if (_event) {
                NoteEvent* ne = _event->event();
                if (_gripType == 0) {
                      qreal x = ChordView::pix2pos(np.x());
                      int x2  = ne->ontime() + ne->len();
                      ne->setOntime(x);
                      ne->setLen(x2 - x);
                      _event->setPos(ChordView::pos2pix(x), _event->pos().y());
                      setPos(0.0, pos().y());
                      GripItem* rg = _view->rightGrip();
                      rg->setPos(x2-x, rg->pos().y());
                      }
                else {
                      qreal x = np.x() - _event->pos().x();
                      setPos(x, pos().y());
                      _event->event()->setLen(x);
                      }
                _view->setDirty(true);
                _event->update();
                }
          }

    //---------------------------------------------------------
    //   ChordItem
    //---------------------------------------------------------

    ChordItem::ChordItem(ChordView* v, Note* n, NoteEvent* e)
       : QGraphicsRectItem(), _view(v), _note(n), _event(e)
          {
          setFlags(flags() | ItemIsSelectable | ItemIsMovable);
          _current  = false;
          int pitch = _event->pitch() + n->pitch();
          int len   = _event->len();
          setRect(0, 0, len, keyHeight/2);
          setBrush(QBrush());
          setSelected(n->selected());
          setData(0, QVariant::fromValue<void*>(n));

          setPos(ChordView::pos2pix(e->ontime()), ChordView::pitch2y(pitch) + keyHeight / 4);
          }

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

    void ChordItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
          {
          QPointF np = mapToScene(event->pos());
          int pitch  = ChordView::y2pitch(np.y());
          int y = ChordView::pitch2y(pitch);
          setPos(pos().x(), y + keyHeight / 4);
          _event->setPitch(pitch - _note->pitch());
          }

    //---------------------------------------------------------
    //   paint
    //---------------------------------------------------------

    void ChordItem::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*)
          {
          int len = _event->len();
          painter->setPen(pen());
          if (_view->curNote() == _note)
                painter->setBrush(_current ? Qt::yellow : Qt::blue);
          else
                painter->setBrush(Qt::gray);
          painter->drawRect(0.0, 0.0, len, keyHeight / 2);
          }

    //---------------------------------------------------------
    //   setCurrent
    //---------------------------------------------------------

    void ChordItem::setCurrent(bool val)
          {
          _current = val;
          update();
          }

    //---------------------------------------------------------
    //   ChordView
    //---------------------------------------------------------

    ChordView::ChordView()
       : QGraphicsView()
          {
          setScene(new QGraphicsScene);
          setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
          setResizeAnchor(QGraphicsView::AnchorUnderMouse);
          // setMouseTracking(true);
          setRubberBandSelectionMode(Qt::IntersectsItemBoundingRect);
          setDragMode(QGraphicsView::RubberBandDrag);
          magStep   = 2;
          chord     = 0;
          _curNote   = 0;
          _evenGrid = true;
          lg        = 0;
          rg        = 0;
          curEvent  = 0;
          ticks     = 1000;
          _dirty    = false;

          scale(6.0, 1.0);
          QAction* a = getAction("delete");
          addAction(a);
          connect(a, SIGNAL(triggered()), SLOT(deleteItem()));
          connect(scene(), SIGNAL(selectionChanged()), SLOT(selectionChanged()));
          }

    //---------------------------------------------------------
    //   drawBackground
    //---------------------------------------------------------

    void ChordView::drawBackground(QPainter* p, const QRectF& r)
          {
          if (chord == 0)
                return;
          QRectF r1(-1000000.0,               0.0, 1000000.0+CHORD_MAP_OFFSET, 1000000.0);
          QRectF r2(ticks + CHORD_MAP_OFFSET, 0.0, 1000000.0, 1000000.0);
          QRectF r3(-1000000.0,     127*keyHeight, 1000000.0+CHORD_MAP_OFFSET, keyHeight);
          QRectF r4(ticks + CHORD_MAP_OFFSET,  127*keyHeight, 1000000.0,        keyHeight);

          QColor bg(0x71, 0x8d, 0xbe);
          QColor bg1 = bg.darker(150);
          QColor bg2 = bg.lighter(150);
          QColor bg3 = bg.darker(75);

          p->fillRect(r, bg);
          p->fillRect(r.intersected(r1), bg1);
          p->fillRect(r.intersected(r2), bg1);

          foreach (const Note* n, chord->notes()) {
                p->fillRect(QRect(CHORD_MAP_OFFSET, (127 - n->pitch()) * keyHeight,
                   1000, keyHeight), bg2);
                }

          p->fillRect(r.intersected(r3), bg3);
          p->fillRect(r.intersected(r4), bg3);

          //---------------------------------------------------
          // draw horizontal grid lines
          //---------------------------------------------------

          qreal y1 = r.y();
          qreal y2 = y1 + r.height();
          qreal x1 = r.x();
          qreal x2 = x1 + r.width();

          int key = floor(y1 / keyHeight);
          qreal y = key * keyHeight;

          for (; key < 127; ++key, y += keyHeight) {
                if (y < y1)
                      continue;
                if (y > y2)
                      break;
                p->setPen(QPen((key % 6) == 5 ? Qt::lightGray : Qt::gray));
                p->drawLine(QLineF(x1, y, x2, y));
                }

          //---------------------------------------------------
          //    draw raster
          //---------------------------------------------------

          if (_evenGrid) {
                for (int x = 0; x <= 1000; x += 50) {
                      if (x % 250)
                            p->setPen(Qt::lightGray);
                      else
                            p->setPen(Qt::black);
                      p->drawLine(pos2pix(x), y1, pos2pix(x), y2);
                      }
                }
          else {
                double step1 = 1000.0 / 3;
                double step2 = step1 / 4;
                for (int i = 0; i < 3; ++i) {
                      p->setPen(Qt::lightGray);
                      for (int k = 1; k < 4; ++k) {
                            int x = lrint(i * step1 + k * step2);
                            p->drawLine(pos2pix(x), y1, pos2pix(x), y2);
                            }
                      p->setPen(Qt::black);
                      int x = lrint(i * step1);
                      p->drawLine(pos2pix(x), y1, pos2pix(x), y2);
                      }
                }
          }

    //---------------------------------------------------------
    //   setChord
    //---------------------------------------------------------

    void ChordView::setChord(Chord* c)
          {
          chord    = c;
          _dirty   = false;
          _pos     = 0;
          _locator = 0;

          scene()->blockSignals(true);
          scene()->clear();
          locatorLine = new QGraphicsLineItem(QLineF(0.0, 0.0, 0.0, keyHeight * 127.0 * 5));
          QPen pen(Qt::red);
          pen.setWidth(2);
          locatorLine->setPen(pen);
          locatorLine->setZValue(1000);       // set stacking order
          locatorLine->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
          scene()->addItem(locatorLine);

          curEvent = 0;
          _curNote  = 0;
          foreach(Note* note, c->notes()) {
                if (note->selected() && _curNote == 0)
                      _curNote = note;
                int n = note->playEvents().size();
                for (int i = 0; i < n; ++i) {
                      NoteEvent* e = &note->playEvents()[i];
                      ChordItem* item = new ChordItem(this, note, e);
                      if (_curNote == note && curEvent == 0)
                            curEvent = item;
                      scene()->addItem(item);
                      }
                }
          lg = new GripItem(0, this);
          rg = new GripItem(1, this);
          lg->setZValue(100);
          rg->setZValue(101);
          lg->setVisible(false);
          rg->setVisible(false);
          scene()->addItem(lg);
          scene()->addItem(rg);

          scene()->blockSignals(false);
          setCurItem(curEvent);
          // selectionChanged();

          scene()->setSceneRect(0.0, 0.0, double(ticks + CHORD_MAP_OFFSET * 2), keyHeight * 127);

          moveLocator();

          //
          // move to something interesting
          //
          QList<QGraphicsItem*> items = scene()->selectedItems();
          QRectF boundingRect;
          foreach(QGraphicsItem* item, items) {
                Note* note = static_cast<Note*>(item->data(0).value<void*>());
                if (note)
                      boundingRect |= item->mapToScene(item->boundingRect()).boundingRect();
                }
          centerOn(boundingRect.center());
          scene()->update();
          }

    //---------------------------------------------------------
    //   moveLocator
    //---------------------------------------------------------

    void ChordView::moveLocator()
          {
          if (_locator >= 0) {
                locatorLine->setVisible(true);
                qreal x = qreal(pos2pix(_locator));
                locatorLine->setPos(QPointF(x, 0.0));
                }
          else
                locatorLine->setVisible(false);
          }

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

    void ChordView::wheelEvent(QWheelEvent* event)
          {
          int step    = event->delta() / 120;
          double xmag = transform().m11();
          double ymag = transform().m22();

          if (event->modifiers() == Qt::ControlModifier) {
                if (step > 0) {
                      for (int i = 0; i < step; ++i) {
                            if (xmag > 10.0)
                                  break;
                            scale(1.1, 1.0);
                            xmag *= 1.1;
                            }
                      }
                else {
                      for (int i = 0; i < -step; ++i) {
                            if (xmag < 0.001)
                                  break;
                            scale(.9, 1.0);
                            xmag *= .9;
                            }
                      }
                emit magChanged(xmag, ymag);

                int tpix  = 1000 * xmag;
                magStep = -5;
                if (tpix <= 4000)
                      magStep = -4;
                if (tpix <= 2000)
                      magStep = -3;
                if (tpix <= 1000)
                      magStep = -2;
                if (tpix <= 500)
                      magStep = -1;
                if (tpix <= 128)
                      magStep = 0;
                if (tpix <= 64)
                      magStep = 1;
                if (tpix <= 32)
                      magStep = 2;
                if (tpix <= 16)
                      magStep = 3;
                if (tpix <= 8)
                      magStep = 4;
                if (tpix <= 4)
                      magStep = 5;
                if (tpix <= 2)
                      magStep = 6;

                //
                // if xpos <= 0, then the scene is centered
                // there is no scroll bar anymore sending
                // change signals, so we have to do it here:
                //
                double xpos = -(mapFromScene(QPointF()).x());
                if (xpos <= 0)
                      emit xposChanged(xpos);
                }
          else if (event->modifiers() == Qt::ShiftModifier) {
                QWheelEvent we(event->pos(), event->delta(), event->buttons(), 0, Qt::Horizontal);
                QGraphicsView::wheelEvent(&we);
                }
          else if (event->modifiers() == 0) {
                QGraphicsView::wheelEvent(event);
                }
          else if (event->modifiers() == (Qt::ShiftModifier | Qt::ControlModifier)) {
                if (step > 0) {
                      for (int i = 0; i < step; ++i) {
                            if (ymag > 3.0)
                                  break;
                            scale(1.0, 1.1);
                            ymag *= 1.1;
                            }
                      }
                else {
                      for (int i = 0; i < -step; ++i) {
                            if (ymag < 0.4)
                                  break;
                            scale(1.0, .9);
                            ymag *= .9;
                            }
                      }
                emit magChanged(xmag, ymag);
                }
          }

    //---------------------------------------------------------
    //   y2pitch
    //---------------------------------------------------------

    int ChordView::y2pitch(int y)
          {
          return 127 - (y / keyHeight);
          }

    //---------------------------------------------------------
    //   pitch2y
    //---------------------------------------------------------

    int ChordView::pitch2y(int pitch)
          {
          return keyHeight * (127 - pitch);
          }

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

    void ChordView::mousePressEvent(QMouseEvent* event)
          {
          if (event->modifiers() & Qt::ControlModifier) {
                QPointF p(mapToScene(event->pos()));
                int pitch = y2pitch(int(p.y()));
                int tick  = int(p.x()) - CHORD_MAP_OFFSET;
                int ticks = 1000 - tick;
                foreach(const NoteEvent& e, _curNote->playEvents()) {
                      if (e.pitch() != pitch)
                            continue;
                      if (tick >= e.ontime() && tick < e.offtime()) {
                            return;     // cannot place an event here
                            }
                      int nticks = e.ontime() - tick;
                      if (nticks > 0)
                            ticks = qMin(ticks, nticks);
                      }

                NoteEvent ne;
                ne.setPitch(pitch);
                ne.setOntime(tick);
                ne.setLen(ticks);
                _curNote->playEvents().append(ne);
                NoteEvent* pne = &_curNote->playEvents()[_curNote->playEvents().size()-1];
                ChordItem* item = new ChordItem(this, _curNote, pne);
                scene()->addItem(item);
                setCurItem(item);
                _dirty = true;
                }
          QGraphicsView::mousePressEvent(event);
          }

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

    void ChordView::mouseMoveEvent(QMouseEvent* event)
          {
          QPointF p(mapToScene(event->pos()));
          int pitch = y2pitch(int(p.y()));
          emit pitchChanged(pitch);
          int tick = int(p.x()) - CHORD_MAP_OFFSET;
          if (tick < 0) {
                tick = 0;
                _pos = -1;
                }
          else
                _pos = tick;
          emit posChanged(_pos);
          QGraphicsView::mouseMoveEvent(event);
          }

    //---------------------------------------------------------
    //   leaveEvent
    //---------------------------------------------------------

    void ChordView::leaveEvent(QEvent* event)
          {
          emit pitchChanged(-1);
          emit posChanged(-1);
          _pos = -1;
          QGraphicsView::leaveEvent(event);
          }

    //---------------------------------------------------------
    //   ensureVisible
    //---------------------------------------------------------

    void ChordView::ensureVisible(int tick)
          {
          tick += CHORD_MAP_OFFSET;
          QPointF pt = mapToScene(0, height() / 2);
          QGraphicsView::ensureVisible(qreal(tick), pt.y(), 240.0, 1.0);
          }

    //---------------------------------------------------------
    //   pos2pix
    //---------------------------------------------------------

    int ChordView::pos2pix(int pos)
          {
          return pos + CHORD_MAP_OFFSET;
          }

    //---------------------------------------------------------
    //   pix2pos
    //---------------------------------------------------------

    int ChordView::pix2pos(int pix)
          {
          return pix - CHORD_MAP_OFFSET;
          }

    //---------------------------------------------------------
    //   selectionChanged
    //---------------------------------------------------------

    void ChordView::selectionChanged()
          {
          QList<QGraphicsItem*> items = scene()->selectedItems();
          if (items.isEmpty())
                setCurItem(0);
          else {
                QGraphicsItem* item = items[0];
                if (item->type() == ChordTypeItem) {
                      ChordItem* ci = static_cast<ChordItem*>(item);
                      setCurItem(ci);
                      }
                }
          }

    //---------------------------------------------------------
    //   deleteItem
    //---------------------------------------------------------

    void ChordView::deleteItem()
          {
          QList<QGraphicsItem*> items = scene()->selectedItems();
          foreach(QGraphicsItem* item, items) {
                if (item->type() == ChordTypeItem) {
                      ChordItem* ci = static_cast<ChordItem*>(item);
                      if (curEvent == ci)
                            setCurItem(0);
                      NoteEvent* event = ci->event();
                      ci->note()->playEvents().removeOne(*event);

                      scene()->removeItem(item);
                      delete item;
                      _dirty = true;
                      }
                }
          }

    //---------------------------------------------------------
    //   setCurItem
    //---------------------------------------------------------

    void ChordView::setCurItem(ChordItem* item)
          {
          if (curEvent)
                curEvent->setCurrent(false);
          curEvent = item;
          bool visible = item != 0;
          lg->setVisible(visible);
          rg->setVisible(visible);
          lg->setEvent(item);
          rg->setEvent(item);
          lg->setParentItem(item);
          rg->setParentItem(item);
          if (visible) {
                lg->setPos(0,   keyHeight / 4);
                rg->setPos(item->event()->len(), keyHeight / 4);
                item->setCurrent(true);
                if (item->note() != _curNote) {
                      _curNote = item->note();
                      _curNote->score()->select(_curNote);
                      _curNote->score()->update();
                      }
                }
          }
    }

↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: _locator, _pos, locatorLine.