//=============================================================================
//  MusE Score
//  Linux Music Score Editor
//  $Id:$
//
//  Copyright (C) 2009 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.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
 
#include "ruler.h"
#include "libmscore/score.h"
 
namespace Ms {
 
#if 0 // yet(?) unused
static const int MAP_OFFSET = 480;
#endif
 
QPixmap* Ruler::markIcon[3];
 
static const char* rmark_xpm[]={
      "18 18 2 1",
      "# c #0000ff",
      ". c None",
      "..................",
      "..................",
      "..................",
      "..................",
      "..................",
      "..................",
      "..................",
      "........##########",
      "........#########.",
      "........########..",
      "........#######...",
      "........######....",
      "........#####.....",
      "........####......",
      "........###.......",
      "........##........",
      "........##........",
      "........##........"};
static const char* lmark_xpm[]={
      "18 18 2 1",
      "# c #0000ff",
      ". c None",
      "..................",
      "..................",
      "..................",
      "..................",
      "..................",
      "..................",
      "..................",
      "##########........",
      ".#########........",
      "..########........",
      "...#######........",
      "....######........",
      ".....#####........",
      "......####........",
      ".......###........",
      "........##........",
      "........##........",
      "........##........"};
static const char* cmark_xpm[]={
      "18 18 2 1",
      "# c #ff0000",
      ". c None",
      "..................",
      "..................",
      "..................",
      "..................",
      "..................",
      "..................",
      "..................",
      "##################",
      ".################.",
      "..##############..",
      "...############...",
      "....##########....",
      ".....########.....",
      "......######......",
      ".......####.......",
      "........##........",
      "........##........",
      "........##........"};
 
 
//---------------------------------------------------------
//   Ruler
//---------------------------------------------------------
 
Ruler::Ruler(QWidget* parent)
   : QWidget(parent)
      {
      if (markIcon[0] == 0) {
            markIcon[0] = new QPixmap(cmark_xpm);
            markIcon[1] = new QPixmap(lmark_xpm);
            markIcon[2] = new QPixmap(rmark_xpm);
            }
      setMouseTracking(true);
      magStep = 0;
      _xpos   = 0;
      _xmag   = 0.1;
      _timeType = TType::TICKS;
      _font2.setPixelSize(14);
      _font2.setBold(true);
      _font1.setPixelSize(10);
      }
 
//---------------------------------------------------------
//   setScore
//---------------------------------------------------------
 
void Ruler::setScore(Score* s, Pos* lc)
      {
      _score = s;
      _locator = lc;
      if (_score)
            _cursor.setContext(_score->tempomap(), _score->sigmap());
      setEnabled(_score != 0);
      }
 
//---------------------------------------------------------
//   setXmag
//---------------------------------------------------------
 
void Ruler::setMag(double x, double /*y*/)
      {
      if (_xmag != x) {
            _xmag = x;
 
            int tpix  = (480 * 4) * _xmag;
            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;
            update();
            }
      }
 
//---------------------------------------------------------
//   setXpos
//---------------------------------------------------------
 
void Ruler::setXpos(int val)
      {
      _xpos = val;
      update();
      }
 
//---------------------------------------------------------
//   pix2pos
//---------------------------------------------------------
 
Pos Ruler::pix2pos(int x) const
      {
      int val = lrint((x + 5 + _xpos)/_xmag - 480);
      if (val < 0)
            val = 0;
      return Pos(_score->tempomap(), _score->sigmap(), val, _timeType);
      }
 
//---------------------------------------------------------
//   pos2pix
//---------------------------------------------------------
 
int Ruler::pos2pix(const Pos& p) const
      {
//      return lrint((p.time(_timeType) + 480) * _xmag) - _xpos - 5;
      return lrint((p.time(_timeType) + 480) * _xmag) - _xpos - 1;
      }
 
//---------------------------------------------------------
//   paintEvent
//---------------------------------------------------------
 
void Ruler::paintEvent(QPaintEvent* e)
      {
      QPainter p(this);
      const QRect& r = e->rect();
 
      static const int mag[7] = {
            1, 1, 2, 5, 10, 20, 50
            };
 
      int x  = r.x();
      int w  = r.width();
      int y  = rulerHeight - 16;
      int h  = 16; // 14;
      int y1 = r.y();
      int rh = r.height();
      if (y1 < rulerHeight) {
            rh -= rulerHeight - y1;
            y1 = rulerHeight;
            }
      int y2 = y1 + rh;
 
      if (x < (-_xpos))
            x = -_xpos;
 
      if (!_score)
            return;
 
      Pos pos1 = pix2pos(x);
      Pos pos2 = pix2pos(x+w);
 
      //---------------------------------------------------
      //    draw raster
      //---------------------------------------------------
 
      int bar1, bar2, beat, tick;
 
      pos1.mbt(&bar1, &beat, &tick);
      pos2.mbt(&bar2, &beat, &tick);
 
      int n = mag[magStep];
 
      bar1 = (bar1 / n) * n;        // round down
      if (bar1 && n >= 2)
            bar1 -= 1;
      bar2 = ((bar2 + n - 1) / n) * n; // round up
 
      for (int bar = bar1; bar <= bar2;) {
            Pos stick(_score->tempomap(), _score->sigmap(), bar, 0, 0);
            if (magStep) {
                  p.setFont(_font2);
                  int x = pos2pix(stick);
                  QString s;
                  s.setNum(bar + 1);
 
                  p.setPen(Qt::black);
                  p.drawLine(x, y, x, y + h);
                  QRect r = QRect(x+2, y, 1000, h);
                  p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, s);
                  p.setPen(Qt::lightGray);
                  if (x > 0)
                        p.drawLine(x, y1, x, y2);
                  }
            else {
                  SigEvent sig = stick.timesig();
                  int z = sig.timesig().numerator();
                  for (int beat = 0; beat < z; beat++) {
                        Pos xx(_score->tempomap(), _score->sigmap(), bar, beat, 0);
                        int xp = pos2pix(xx);
                        if (xp < 0)
                              continue;
                        QString s;
                        QRect r(xp+2, y + 1, 1000, h);
                        int y3;
                        int num;
                        if (beat == 0) {
                              num = bar + 1;
                              y3  = y + 2;
                              p.setFont(_font2);
                              }
                        else {
                              num = beat + 1;
                              y3  = y + 8;
                              p.setFont(_font1);
                              r.moveTop(r.top() + 1);
                              }
                        s.setNum(num);
                        p.setPen(Qt::black);
                        p.drawLine(xp, y3, xp, y+h);
                        p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, s);
                        p.setPen(beat == 0 ? Qt::lightGray : Qt::gray);
                        if (xp > 0)
                              p.drawLine(xp, y1, xp, y2);
                        }
                  }
            if (bar == 0 && n >= 2)
                  bar += (n-1);
            else
                  bar += n;
            }
      //
      //  draw mouse cursor marker
      //
      p.setPen(Qt::black);
      if (_cursor.valid()) {
            int xp = pos2pix(_cursor);
            if (xp >= x && xp < x+w)
                  p.drawLine(xp, 0, xp, rulerHeight);
            }
      static const QColor lcColors[3] = { Qt::red, Qt::blue, Qt::blue };
      for (int i = 0; i < 3; ++i) {
            if (!_locator[i].valid())
                  continue;
            p.setPen(lcColors[i]);
            int xp      = pos2pix(_locator[i]);
            QPixmap* pm = markIcon[i];
            // int pw = (pm->width() + 1) / 2;
            int pw = pm->width() / 2;
            int x1 = x - pw;
            int x2 = x + w + pw;
            if (xp >= x1 && xp < x2)
                  p.drawPixmap(xp - pw, y-2, *pm);
            }
      }
 
//---------------------------------------------------------
//   mousePressEvent
//---------------------------------------------------------
 
void Ruler::mousePressEvent(QMouseEvent* e)
      {
      moveLocator(e);
      }
 
//---------------------------------------------------------
//   mouseMoveEvent
//---------------------------------------------------------
 
void Ruler::mouseMoveEvent(QMouseEvent* e)
      {
      moveLocator(e);
      }
 
//---------------------------------------------------------
//   moveLocator
//---------------------------------------------------------
 
void Ruler::moveLocator(QMouseEvent* e)
      {
      Pos pos(pix2pos(e->pos().x()));
      if (e->buttons() & Qt::LeftButton)
            emit locatorMoved(0, pos);
      else if (e->buttons() & Qt::MidButton)
            emit locatorMoved(1, pos);
      else if (e->buttons() & Qt::RightButton)
            emit locatorMoved(2, pos);
      }
 
//---------------------------------------------------------
//   leaveEvent
//---------------------------------------------------------
 
void Ruler::leaveEvent(QEvent*)
      {
      _cursor.setInvalid();
      emit posChanged(_cursor);
      update();
      }
 
//---------------------------------------------------------
//   setPos
//---------------------------------------------------------
 
void Ruler::setPos(const Pos& pos)
      {
      if (_cursor != pos) {
            int x1 = pos2pix(_cursor);
            int x2 = pos2pix(pos);
            if (x1 > x2) {
                  int tmp = x2;
                  x2 = x1;
                  x1 = tmp;
                  }
            update(QRect(x1-1, 0, x2-x1+2, height()));
            _cursor = pos;
            }
      }
}
 

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