Logo Search packages:      
Sourcecode: canorus version File versions  Download package

void CAMainWin::insertMusElementAt ( const QPoint  coords,
CAScoreViewPort v 
)

This method places the currently prepared music element in CAMusElementFactory to the staff or voice, dependent on the music element type and the viewport coordinates.

Definition at line 2215 of file mainwin.cpp.

References CATuplet::actualNumber(), CARest::composeRests(), CAMusElementFactory::configureBarline(), CAMusElementFactory::configureClef(), CAMusElementFactory::configureFunctionMark(), CAMusElementFactory::configureKeySignature(), CAMusElementFactory::configureMark(), CAMusElementFactory::configureNote(), CAMusElementFactory::configureRest(), CAMusElementFactory::configureSlur(), CAMusElementFactory::configureTimeSignature(), CAVoice::containsPitch(), CAScoreViewPort::currentContext(), currentVoice(), CANote::diatonicPitch(), CAMusElementFactory::emptyMusElem(), CASheet::getChord(), CANote::getChord(), CAVoice::getNoteList(), CAVoice::insert(), CANote::isPartOfChord(), CAVoice::lastTimeEnd(), CAMusElementFactory::musElement(), CAScoreViewPort::musElementsAt(), CAMusElement::musElementType(), CAScoreViewPort::nearestLeftElement(), CAScoreViewPort::nearestRightElement(), CAVoice::next(), CATuplet::noteList(), CATuplet::number(), CANote::phrasingSlurEnd(), CANote::phrasingSlurStart(), CAMusElementFactory::placeAutoBar(), CAPlayableLength::playableLengthToTimeLength(), playImmediately(), CAVoice::remove(), CAScoreViewPort::selection(), CAScoreViewPort::selectMElement(), CAScoreViewPort::setDrawShadowNoteAccs(), CAMusElementFactory::setMusElement(), CAMusElementFactory::setNoteExtraAccs(), CAScoreViewPort::setShadowNoteLength(), CAScoreViewPort::sheet(), CANote::slurEnd(), CANote::slurStart(), CAMusElementFactory::slurType(), CAStaff::synchronizeVoices(), CANote::tieStart(), CAMusElement::timeEnd(), CAMusElement::timeLength(), CATuplet::timeLength(), CAMusElement::timeStart(), CAScoreViewPort::updateHelpers(), and CAPlayable::voice().

Referenced by scoreViewPortMousePress().

                                                                          {
      CADrawableContext *drawableContext = v->currentContext();

      CAStaff *staff=0;
      CADrawableStaff *drawableStaff = 0;
      if (drawableContext) {
            drawableStaff = dynamic_cast<CADrawableStaff*>(drawableContext);
            staff = dynamic_cast<CAStaff*>(drawableContext->context());
      }

      CADrawableMusElement *drawableRight = v->nearestRightElement(coords.x(), coords.y(), v->currentContext());

      CAMusElement *right=0;
      if ( drawableRight )
            right = drawableRight->musElement();

      bool success=false;

      if (!drawableContext)
            return;

      CACanorus::undo()->createUndoCommand( document(), tr("insertion of music element", "undo") );

      switch ( musElementFactory()->musElementType() ) {
            case CAMusElement::Clef: {
                  if (staff)
                        success = musElementFactory()->configureClef( staff , right );
                  break;
            }
            case CAMusElement::KeySignature: {
                  if ( staff )
                        success = musElementFactory()->configureKeySignature( staff, right );
                  break;
            }
            case CAMusElement::TimeSignature: {
                  if ( staff )
                        success = musElementFactory()->configureTimeSignature( staff, right );
                  break;
            }
            case CAMusElement::Barline: {
                  if ( staff )
                        success = musElementFactory()->configureBarline( staff, right );
                  break;
            }
            case CAMusElement::Mark: {
                  if ( v->musElementsAt( coords.x(), coords.y() ).size() )
                        success = musElementFactory()->configureMark( v->musElementsAt( coords.x(), coords.y() )[0]->musElement() );
                  break;
            }
            case CAMusElement::Note: { // Do we really need to do all that here??
                  CAVoice *voice = currentVoice();

                  if ( !voice )
                        break;

                  CADrawableMusElement *left = v->nearestLeftElement( coords.x(), coords.y(), voice ); // use nearestLeft search because it searches left borders
                  CADrawableMusElement *dright = v->nearestRightElement( coords.x(), coords.y(), voice );

                  if ( left && left->musElement() && left->musElement()->musElementType() == CAMusElement::Note &&
                       left->xPos() <= coords.x() && (left->width() + left->xPos() >= coords.x()) ) {

                        // user clicked inside x borders of the note - add a note to the chord

                        if ( voice->containsPitch( drawableStaff->calculatePitch(coords.x(), coords.y()), left->musElement()->timeStart() ) )
                              break;      // user clicked on an already placed note or wanted to place illegal length (not the one the chord is of) - return and do nothing

                        success = musElementFactory()->configureNote( drawableStaff->calculatePitch(coords.x(), coords.y()), voice, left->musElement(), true );
                  } else
                  if ( left && left->musElement() && left->musElement()->musElementType() == CAMusElement::Rest &&
                       left->xPos() <= coords.x() && (left->width() + left->xPos() >= coords.x()) ) {

                        // user clicked inside x borders of the rest - replace the rest/rests with the note
                        // same code for the Rest insertion

                        CATuplet *tuplet = static_cast<CAPlayable*>(left->musElement())->tuplet();
                        QList<CAPlayable*> noteList; int number; int actualNumber;
                        if ( tuplet  ) {
                              noteList = tuplet->noteList();
                              number = tuplet->number();
                              actualNumber = tuplet->actualNumber();
                              delete tuplet;
                        }

                        int timeSum = left->musElement()->timeLength();
                        int timeLength = CAPlayableLength::playableLengthToTimeLength( musElementFactory()->playableLength() );

                        CAMusElement *next;
                        while ( (next=voice->next(left->musElement())) &&
                                next->musElementType() == CAMusElement::Rest &&
                                timeSum < timeLength ) {
                              voice->remove(next);
                              noteList.removeAll(static_cast<CAPlayable*>(next));
                              timeSum += next->timeLength();
                        }

                        int tupIndex = noteList.indexOf( static_cast<CAPlayable*>(left->musElement()) );
                        noteList.removeAll( static_cast<CAPlayable*>(left->musElement()) );
                        voice->remove( left->musElement() );

                        if (timeSum - timeLength > 0) {
                              // we removed too many rests - insert the delta of the missing rests
                              QList<CARest*> rests = CARest::composeRests( timeSum - timeLength, next?next->timeStart():voice->lastTimeEnd(), voice, CARest::Normal );
                              for (int i=rests.size()-1; i>=0; i--) {
                                    voice->insert(next, rests[i]);
                                    noteList.insert( tupIndex, rests[i] );
                              }
                              next = rests[rests.size()-1];
                        }

                        success = musElementFactory()->configureNote( drawableStaff->calculatePitch(coords.x(), coords.y()), voice, next, false );
                        if ( success && CACanorus::settings()->autoBar() )
                              CAMusElementFactory::placeAutoBar( static_cast<CAPlayable*>(musElementFactory()->musElement()) );

                        if( success )
                              noteList.insert( tupIndex, static_cast<CAPlayable*>(musElementFactory()->musElement()) );

                        if ( success && tuplet ) {
                              new CATuplet( number, actualNumber, noteList );
                        }
                  } else {

                        // user clicked outside x borders of the note or rest

                        if ( dright && dright->musElement() && dright->musElement()->isPlayable() && static_cast<CAPlayable*>(dright->musElement())->tuplet() && !static_cast<CAPlayable*>(dright->musElement())->isFirstInTuplet() ) {
                              delete static_cast<CAPlayable*>(dright->musElement())->tuplet();
                        }

                        success = musElementFactory()->configureNote( drawableStaff->calculatePitch(coords.x(), coords.y()), voice, dright?dright->musElement():0, false );
                        if ( success && CACanorus::settings()->autoBar() )
                              CAMusElementFactory::placeAutoBar( static_cast<CAPlayable*>(musElementFactory()->musElement()) );

                        if ( success && uiTupletType->isChecked() ) {
                              QList<CAPlayable*> elements;
                              elements << static_cast<CAPlayable*>(musElementFactory()->musElement());

                              for (int i=1; i<uiTupletNumber->value(); i++) {
                                    musElementFactory()->configureRest( voice, dright?dright->musElement():0 );
                                    elements << static_cast<CAPlayable*>(musElementFactory()->musElement());
                              }
                              musElementFactory()->setMusElement( elements[0] );

                              new CATuplet( uiTupletNumber->value(), uiTupletActualNumber->value(), elements );
                        }
                  }

                  if ( success ) {
                        if ( musElementFactory()->musElement()->musElementType()==CAMusElement::Note && CACanorus::settings()->playInsertedNotes() ) {
                              playImmediately( QList<CAMusElement*>() << musElementFactory()->musElement() );
                        }

                        musElementFactory()->setNoteExtraAccs( 0 );
                        v->setDrawShadowNoteAccs( false );
                        v->setShadowNoteLength( musElementFactory()->playableLength() );
                        v->updateHelpers();
                  }
                  break;
            }
            case CAMusElement::Rest: {
                  CAVoice *voice = currentVoice();

                  if ( !voice )
                        break;

                  CADrawableMusElement *left = v->nearestLeftElement( coords.x(), coords.y(), voice ); // use nearestLeft search because it searches left borders
                  CADrawableMusElement *dright = v->nearestRightElement( coords.x(), coords.y(), voice );

                  if ( left && left->musElement() && left->musElement()->isPlayable() &&
                       left->xPos() <= coords.x() && (left->width() + left->xPos() >= coords.x()) ) {

                        // user clicked inside x borders of the rest or note - replace the rest/rests with the rest
                        // same code for the Note insertion

                        CATuplet *tuplet = static_cast<CAPlayable*>(left->musElement())->tuplet();
                        QList<CAPlayable*> noteList; int number; int actualNumber;
                        if ( tuplet  ) {
                              noteList = tuplet->noteList();
                              number = tuplet->number();
                              actualNumber = tuplet->actualNumber();
                              delete tuplet;
                        }

                        int timeSum = left->musElement()->timeLength();
                        int timeLength = CAPlayableLength::playableLengthToTimeLength( musElementFactory()->playableLength() );

                        CAMusElement *next;
                        while ( (next=voice->next(left->musElement())) &&
                                next->musElementType() == CAMusElement::Rest &&
                                timeSum < timeLength ) {
                              voice->remove(next);
                              noteList.removeAll(static_cast<CAPlayable*>(next));
                              timeSum += next->timeLength();
                        }

                        int tupIndex = noteList.indexOf( static_cast<CAPlayable*>(left->musElement()) );
                        noteList.removeAll( static_cast<CAPlayable*>(left->musElement()) );
                        voice->remove( left->musElement() );

                        if (timeSum - timeLength > 0) {
                              // we removed too many rests - insert the delta of the missing rests
                              QList<CARest*> rests = CARest::composeRests( timeSum - timeLength, next?next->timeStart():voice->lastTimeEnd(), voice, CARest::Normal );
                              for (int i=rests.size()-1; i>=0; i--) {
                                    voice->insert(next, rests[i]);
                                    noteList.insert( tupIndex, rests[i] );
                              }
                              next = rests[rests.size()-1];
                        }

                        success = musElementFactory()->configureRest( voice, next );
                        if ( success && CACanorus::settings()->autoBar() )
                              CAMusElementFactory::placeAutoBar( static_cast<CAPlayable*>(musElementFactory()->musElement()) );

                        if( success )
                              noteList.insert( tupIndex, static_cast<CAPlayable*>(musElementFactory()->musElement()) );

                        if( success && tuplet ) {
                              new CATuplet( number, actualNumber, noteList );
                        }
                  } else {
                        if ( dright && dright->musElement() && dright->musElement()->isPlayable() && static_cast<CAPlayable*>(dright->musElement())->tuplet() && !static_cast<CAPlayable*>(dright->musElement())->isFirstInTuplet() ) {
                              delete static_cast<CAPlayable*>(dright->musElement())->tuplet();
                        }

                        success = musElementFactory()->configureRest( voice, dright?dright->musElement():0 );
                        if ( success && CACanorus::settings()->autoBar() )
                              CAMusElementFactory::placeAutoBar( static_cast<CAPlayable*>(musElementFactory()->musElement()) );
                  }

                  if (success) {
                        v->setShadowNoteLength( musElementFactory()->playableLength() );
                        v->updateHelpers();
                  }

                  break;
            }
            case CAMusElement::Slur: {
                  // Insert tie, slur or phrasing slur
                  if ( v->selection().size() ) { // start note has to always be selected
                        CANote *noteStart = (currentScoreViewPort()->selection().front()->musElement()?dynamic_cast<CANote*>(currentScoreViewPort()->selection().front()->musElement()):0);
                        CANote *noteEnd = (currentScoreViewPort()->selection().back()->musElement()?dynamic_cast<CANote*>(currentScoreViewPort()->selection().back()->musElement()):0);

                        // Insert Tie
                        if ( noteStart && musElementFactory()->slurType()==CASlur::TieType ) {
                              noteEnd = 0; // find a fresh next note
                              QList<CANote*> noteList = noteStart->voice()->getNoteList();

                              if ( noteStart->tieStart() ) {
                                    break; // return, if the tie already exists
                              } else {
                                    // create a new tie
                                    for (int i=0; i<noteList.count() && noteList[i]->timeStart()<=noteStart->timeEnd(); i++) {
                                          if ( noteList[i]->timeStart()==noteStart->timeEnd() && noteList[i]->diatonicPitch()==noteStart->diatonicPitch() ) {
                                                noteEnd = noteList[i];
                                                break;
                                          }
                                    }
                              }
                              success = musElementFactory()->configureSlur( staff, noteStart, noteEnd );
                        } else
                        // Insert slur or phrasing slur
                        if ( noteStart && noteEnd && noteStart != noteEnd && (musElementFactory()->slurType()==CASlur::SlurType || musElementFactory()->slurType()==CASlur::PhrasingSlurType) ) {
                              if (noteStart->isPartOfChord()) noteStart = noteStart->getChord().at(0);
                              if (noteEnd->isPartOfChord()) noteEnd = noteEnd->getChord().at(0);
                              QList<CANote*> noteList = noteStart->voice()->getNoteList();
                              int end = noteList.indexOf(noteEnd);
                              for (int i=noteList.indexOf(noteStart); i<=end; i++)
                                    if ( musElementFactory()->slurType()==CASlur::SlurType && (noteList[i]->slurStart() || noteList[i]->slurEnd()) ||
                                         musElementFactory()->slurType()==CASlur::PhrasingSlurType && (noteList[i]->phrasingSlurStart() || noteList[i]->phrasingSlurEnd()) )
                                          return;

                              if (musElementFactory()->slurType()==CASlur::SlurType && (noteStart->slurStart() || noteEnd->slurEnd()) ||
                                  musElementFactory()->slurType()==CASlur::PhrasingSlurType && (noteStart->phrasingSlurStart() || noteEnd->phrasingSlurEnd()))
                                    break; // return, if the slur already exist
                              success = musElementFactory()->configureSlur( staff, noteStart, noteEnd );
                        }
                  }
                  break;
            }
            case CAMusElement::FunctionMark: {
                  // Insert function mark
                  if (drawableContext->context()->contextType()==CAContext::FunctionMarkContext) {
                        CAFunctionMarkContext *fmc = static_cast<CAFunctionMarkContext*>(drawableContext->context());
                        CADrawableMusElement *dLeft = v->nearestLeftElement(coords.x(), coords.y());
                        int timeStart = 0;
                        if ( dLeft ) // find the nearest left element from the cursor
                              timeStart = dLeft->musElement()->timeStart();
                        QList<CAPlayable*> chord = currentSheet()->getChord(timeStart);
                        int timeLength = chord.size()?chord[0]->timeLength():256;
                        for (int i=0; i<chord.size(); i++) // find the shortest note in the chord
                              if (chord[i]->timeLength()-(timeStart-chord[i]->timeStart())<timeLength)
                                    timeLength = chord[i]->timeLength()-(timeStart-chord[i]->timeStart());

                        success = musElementFactory()->configureFunctionMark( fmc, timeStart, timeLength );
                  }
                  break;
            }
      }

      if (success) {
            if (staff)
                  staff->synchronizeVoices();

            CACanorus::undo()->pushUndoCommand();
            CACanorus::rebuildUI(document(), v->sheet());
            v->selectMElement( musElementFactory()->musElement() );
            musElementFactory()->emptyMusElem();
      }
}


Generated by  Doxygen 1.6.0   Back to index