예제 #1
0
파일: utils.cpp 프로젝트: CFrei/MuseScore
Segment* Score::tick2segmentEnd(int track, int tick) const
      {
      Measure* m = tick2measure(tick);
      if (m == 0) {
            qDebug("tick2segment(): not found tick %d\n", tick);
            return 0;
            }
      // loop over all segments
      for (Segment* segment = m->first(Segment::SegChordRest); segment; segment = segment->next(Segment::SegChordRest)) {
            ChordRest* cr = static_cast<ChordRest*>(segment->element(track));
            if (!cr)
                  continue;
            // TODO LVI: check if following is correct, see exceptions in
            // ExportMusicXml::chord() and ExportMusicXml::rest()
            int endTick = cr->tick() + cr->actualTicks();
            if (endTick < tick)
                  continue; // not found yet
            else if (endTick == tick) {
                  return segment; // found it
                  }
            else {
                  // endTick > tick (beyond the tick we are looking for)
                  return 0;
                  }
            }
      return 0;
      }
예제 #2
0
ChordRest* Selection::lastChordRest(int track) const
      {
      if (_el.size() == 1) {
            Element* el = _el[0];
            if (el && el->type() == Element::NOTE)
                  return static_cast<ChordRest*>(el->parent());
            else if (el->type() == Element::CHORD || el->type() == Element::REST)
                  return static_cast<ChordRest*>(el);
            return 0;
            }
      ChordRest* cr = 0;
      for (auto i = _el.begin(); i != _el.end(); ++i) {
            Element* el = *i;
            if (el->type() == Element::NOTE)
                  el = ((Note*)el)->chord();
            if (el->isChordRest() && static_cast<ChordRest*>(el)->segment()->segmentType() == Segment::SegChordRest) {
                  if (track != -1 && el->track() != track)
                        continue;
                  if (cr) {
                        if (((ChordRest*)el)->tick() >= cr->tick())
                              cr = (ChordRest*)el;
                        }
                  else
                        cr = (ChordRest*)el;
                  }
            }
      return cr;
      }
예제 #3
0
ChordRest* Selection::firstChordRest(int track) const
      {
      if (_el.size() == 1) {
            Element* el = _el[0];
            if (el->type() == Element::NOTE)
                  return static_cast<ChordRest*>(el->parent());
            else if (el->type() == Element::REST)
                  return static_cast<ChordRest*>(el);
            return 0;
            }
      ChordRest* cr = 0;
      foreach (Element* el, _el) {
            if (el->type() == Element::NOTE)
                  el = el->parent();
            if (el->isChordRest()) {
                  if (track != -1 && el->track() != track)
                        continue;
                  if (cr) {
                        if (static_cast<ChordRest*>(el)->tick() < cr->tick())
                              cr = static_cast<ChordRest*>(el);
                        }
                  else
                        cr = static_cast<ChordRest*>(el);
                  }
            }
      return cr;
      }
예제 #4
0
void MuseScore::tupletDialog()
      {
      if (!cs)
            return;
      ChordRest* cr = cs->getSelectedChordRest();
      if (cr == 0)
            return;
      TupletDialog td;
      if (!td.exec())
            return;

      Tuplet* tuplet = new Tuplet(cs);
      tuplet->setTrack(cr->track());
      tuplet->setTick(cr->tick());
      td.setupTuplet(tuplet);
      //      tuplet->setRatio(tuplet->ratio().reduced());
      Fraction f1(cr->duration());
      tuplet->setDuration(f1);
      Fraction f = f1 * tuplet->ratio();
      f.reduce();

      printf("len %s  ratio %s  base %s\n",
         qPrintable(f1.print()),
         qPrintable(tuplet->ratio().print()),
         qPrintable(f.print()));

      tuplet->setBaseLen(Fraction(1, f.denominator()));

      Measure* measure = cr->measure();
      tuplet->setParent(measure);

      cs->cmdCreateTuplet(cr, tuplet);
      }
예제 #5
0
파일: menus.cpp 프로젝트: CafeCat/MuseScore
void MuseScore::addTempo()
{
    ChordRest* cr = cs->getSelectedChordRest();
    if (!cr)
        return;
//      double bps = 2.0;

    SigEvent event = cs->sigmap()->timesig(cr->tick());
    Fraction f = event.nominal();

    QString text(QString("%1%2 = 80").arg(QChar(0xd834)).arg(QChar(0xdd5f)));
    switch (f.denominator()) {
    case 1:
        text = QString("%1%2 = 80").arg(QChar(0xd834)).arg(QChar(0xdd5d));
        break;
    case 2:
        text = QString("%1%2 = 80").arg(QChar(0xd834)).arg(QChar(0xdd5e));
        break;
    case 4:
        text = QString("%1%2 = 80").arg(QChar(0xd834)).arg(QChar(0xdd5f));
        break;
    case 8:
        if(f.numerator() % 3 == 0)
            text = QString("%1%2%3%4 = 80").arg(QChar(0xd834)).arg(QChar(0xdd5f)).arg(QChar(0xd834)).arg(QChar(0xdd6d));
        else
            text = QString("%1%2 = 80").arg(QChar(0xd834)).arg(QChar(0xdd60));
        break;
    case 16:
        if(f.numerator() % 3 == 0)
            text = QString("%1%2%3%4 = 80").arg(QChar(0xd834)).arg(QChar(0xdd60)).arg(QChar(0xd834)).arg(QChar(0xdd6d));
        else
            text = text = QString("%1%2 = 80").arg(QChar(0xd834)).arg(QChar(0xdd61));
        break;
    case 32:
        if(f.numerator() % 3 == 0)
            text = QString("%1%2%3%4 = 80").arg(QChar(0xd834)).arg(QChar(0xdd61)).arg(QChar(0xd834)).arg(QChar(0xdd6d));
        else
            text = text = QString("%1%2 = 80").arg(QChar(0xd834)).arg(QChar(0xdd62));
        break;
    case 64:
        if(f.numerator() % 3 == 0)
            text = QString("%1%2%3%4 = 80").arg(QChar(0xd834)).arg(QChar(0xdd62)).arg(QChar(0xd834)).arg(QChar(0xdd6d));
        else
            text = text = QString("%1%2 = 80").arg(QChar(0xd834)).arg(QChar(0xdd63));
        break;
    default:
        break;
    }

    TempoText* tt = new TempoText(cs);
    tt->setParent(cr->segment());
    tt->setTrack(cr->track());
    tt->setText(text);
    tt->setFollowText(true);
    //tt->setTempo(bps);
    cs->undoAddElement(tt);
    cv->startEdit(tt);
}
예제 #6
0
void MuseScore::addTempo()
      {
      ChordRest* cr = cs->getSelectedChordRest();
      if (!cr)
            return;
//      double bps = 2.0;

      SigEvent event = cs->sigmap()->timesig(cr->tick());
      Fraction f = event.nominal();
      QString text("<sym>noteQuarterUp</sym> = 80");
      switch (f.denominator()) {
            case 1:
                  text = "<sym>noteWhole</sym> = 80";
                  break;
            case 2:
                  text = "<sym>noteHalfUp</sym> = 80";
                  break;
            case 4:
                  text = "<sym>noteQuarterUp</sym> = 80";
                  break;
            case 8:
                  if(f.numerator() % 3 == 0)
                        text = "<sym>noteQuarterUp</sym><sym>textAugmentationDot</sym> = 80";
                  else
                        text = "<sym>note8thUp</sym> = 80";
                  break;
            case 16:
                  if(f.numerator() % 3 == 0)
                        text = text = "<sym>note8thUp</sym><sym>textAugmentationDot</sym> = 80";
                  else
                        text = "<sym>note16thUp</sym> = 80";
                  break;
            case 32:
                  if(f.numerator() % 3 == 0)
                        text = "<sym>note16thUp</sym><sym>textAugmentationDot</sym> = 80";
                  else
                        text = "<sym>note32thUp</sym> = 80";
                  break;
            case 64:
                  if(f.numerator() % 3 == 0)
                        text = "<sym>note32thUp</sym><sym>textAugmentationDot</sym> = 80";
                  else
                        text = "<sym>note64thUp</sym> = 80";
                  break;
            default:
                  break;
            }

      TempoText* tt = new TempoText(cs);
      tt->setParent(cr->segment());
      tt->setTrack(cr->track());
      tt->setText(text);
      tt->setFollowText(true);
      //tt->setTempo(bps);
      cs->undoAddElement(tt);
      cv->startEdit(tt);
      }
예제 #7
0
int Selection::tickStart() const
      {
      switch (_state) {
            case SelState::RANGE:
                  return _startSegment->tick();
                  break;
            case SelState::LIST: {
                  ChordRest* cr = firstChordRest();
                  return (cr) ? cr->tick() : -1;
                  break;
                  }
            default:
                  return -1;
            }
      }
예제 #8
0
ChordRest* Selection::firstChordRest(int track) const
      {
      ChordRest* cr = 0;
      foreach (Element* el, _el) {
            if (el->type() == NOTE)
                  el = el->parent();
            if (el->isChordRest()) {
                  if (track != -1 && el->track() != track)
                        continue;
                  if (cr) {
                        if (static_cast<ChordRest*>(el)->tick() < cr->tick())
                              cr = static_cast<ChordRest*>(el);
                        }
                  else
                        cr = static_cast<ChordRest*>(el);
                  }
            }
      return cr;
      }
예제 #9
0
ChordRest* Selection::lastChordRest(int track) const
      {
      ChordRest* cr = 0;
      for (ciElement i = _el.begin(); i != _el.end(); ++i) {
            Element* el = *i;
            if (el->type() == NOTE)
                  el = ((Note*)el)->chord();
            if (el->isChordRest() && static_cast<ChordRest*>(el)->segment()->subtype() == SegChordRest) {
                  if (track != -1 && el->track() != track)
                        continue;
                  if (cr) {
                        if (((ChordRest*)el)->tick() >= cr->tick())
                              cr = (ChordRest*)el;
                        }
                  else
                        cr = (ChordRest*)el;
                  }
            }
      return cr;
      }
예제 #10
0
int Selection::tickEnd() const
      {
      switch (_state) {
            case SelState::RANGE: {
                  if (_endSegment) {
                        return _endSegment->tick();
                        }
                  else { // endsegment == 0 if end of score
                      Measure* m = _score->lastMeasure();
                      return m->tick() + m->ticks();
                      }
                  break;
                  }
            case SelState::LIST: {
                  ChordRest* cr = lastChordRest();
                  return (cr) ? cr->tick() : -1;
                  break;
                  }
            default:
                  return -1;
            }
      }
예제 #11
0
void Lyrics::layout1()
      {
      setPos(textStyle().offset(spatium()));
      Text::layout1();
      if (!parent()) // palette & clone trick
          return;

      ChordRest* cr = chordRest();
      const QList<Lyrics*>* ll = &(cr->lyricsList());

      qreal lh = lineSpacing() * score()->styleD(StyleIdx::lyricsLineHeight);
      int line = ll->indexOf(this);
      qreal y  = lh * line + point(score()->styleS(StyleIdx::lyricsDistance));
      qreal x  = 0.0;

      //
      // parse leading verse number and/or punctuation, so we can factor it into layout separately
      // TODO: provide a way to disable this
      //
      bool hasNumber = false; // _verseNumber;
      qreal adjust = 0.0;
      QString s = plainText(true);
      // find:
      // 1) string of numbers and non-word characters at start of syllable
      // 2) at least one other character (indicating start of actual lyric)
      QRegularExpression leadingPattern("(^[\\d\\W]+)([^\\d\\W]+)");
      QRegularExpressionMatch leadingMatch = leadingPattern.match(s);
      if (leadingMatch.hasMatch()) {
            // leading string
            QString s1 = leadingMatch.captured(1);
            // actual lyric
            //QString s2 = leadingMatch.captured(2);
            Text leading(*this);
            leading.setPlainText(s1);
            leading.layout1();
            adjust = leading.width();
            if (!s1.isEmpty() && s1[0].isDigit())
                  hasNumber = true;
            }

      if (textStyle().align() & AlignmentFlags::HCENTER) {
            //
            // center under notehead, not origin
            // however, lyrics that are melismas or have verse numbers will be forced to left alignment
            // TODO: provide a way to disable the automatic left alignment
            //
            qreal maxWidth;
            if (cr->type() == Element::Type::CHORD)
                  maxWidth = static_cast<Chord*>(cr)->maxHeadWidth();
            else
                  maxWidth = cr->width();       // TODO: exclude ledger line for multivoice rest?
            qreal nominalWidth = symWidth(SymId::noteheadBlack);
            if (!isMelisma() && !hasNumber)     // center under notehead
                  x +=  nominalWidth * .5 - cr->x() - adjust * 0.5;
            else                                // force left alignment
                  x += (width() + nominalWidth - maxWidth) * .5 - cr->x() - adjust;
            }
      else {
            // even for left aligned syllables, ignore leading verse numbers and/or punctuation
            x -= adjust;
            }

      rxpos() += x;
      rypos() += y;

      if (_ticks > 0 || _syllabic == Syllabic::BEGIN || _syllabic == Syllabic::MIDDLE) {
            if (_separator == nullptr) {
                  _separator = new LyricsLine(score());
                  _separator->setTick(cr->tick());
                  score()->addUnmanagedSpanner(_separator);
                  }
            _separator->setParent(this);
            _separator->setTick(cr->tick());
            _separator->setTrack(track());
            _separator->setTrack2(track());
#if defined(USE_FONT_DASH_METRIC)
            // if font parameters different from font cached values, compute new dash values from font metrics
            if (textStyle().family() != g_fontFamily && textStyle().size() != g_fontSize) {
                  QFontMetricsF     fm    = textStyle().fontMetrics(spatium());
                  QRectF            r     = fm.tightBoundingRect("\u2013");   // U+2013 EN DASH
                  g_cachedDashY           = _dashY          = r.y() + (r.height() * HALF);
                  g_cachedDashLength      = _dashLength     = r.width();
   #if defined(USE_FONT_DASH_TICKNESS)
                  g_cachedDashThickness   = _dashThickness  = r.height();
   #endif
                  g_fontFamily            = textStyle().family();
                  g_fontSize              = textStyle().size();
                  }
            // if same font, use cached values
            else {
                  _dashY                  = g_cachedDashY;
                  _dashLength             = g_cachedDashLength;
   #if defined(USE_FONT_DASH_TICKNESS)
                  _dashThickness          = g_cachedDashThickness;
   #endif
                  }
#endif
            }
      else
            if (_separator != nullptr) {
                  _separator->unchain();
                  delete _separator;
                  _separator = nullptr;
                  }
      }