@@ -982,6 +982,59 @@ void Score::pasteSymbols(XmlReader& e, ChordRest* dst)
982982            }                             //  inner while readNextstartElement()
983983      }                                   //  pasteSymbolList()
984984
985+ static  ChordRest* replaceWithRest (ChordRest* target)
986+       {
987+       target->score ()->undoRemoveElement (target);
988+       return  target->score ()->addRest (target->segment (), target->track (), target->ticks (), target->tuplet ());
989+       }
990+ 
991+ static  Note* prepareTarget (ChordRest* target, Note* with, const  Fraction& duration)
992+       {
993+       if  (!target->segment ()->element (target->track ()))
994+            return  nullptr ; //  target was removed by previous operation, ignore this
995+       if  (target->isChord () && target->ticks () > duration)
996+             target = replaceWithRest (target); //  prevent unexpected note splitting
997+       Segment* segment = target->segment ();
998+       if  (segment->measure ()->isMMRest ()) {
999+             Measure* m = segment->measure ()->mmRestFirst ();
1000+             segment = m->findSegment (SegmentType::ChordRest, m->tick ());
1001+             }
1002+       segment = target->score ()->setNoteRest (segment, target->track (),
1003+                                              with->noteVal (), duration, Direction::AUTO, false , false , &target->score ()->inputState ());
1004+       return  toChord (segment->nextChordRest (target->track ()))->upNote ();
1005+       }
1006+ 
1007+ static  Element* prepareTarget (Element* target, Note* with, const  Fraction& duration)
1008+       {
1009+       if  (target->isNote () && toNote (target)->chord ()->ticks () != duration)
1010+             return  prepareTarget (toNote (target)->chord (), with, duration);
1011+       if  (target->isChordRest () && toChordRest (target)->ticks () != duration)
1012+             return  prepareTarget (toChordRest (target), with, duration);
1013+       return  target;
1014+       }
1015+ 
1016+ static  bool  canPasteStaff (XmlReader& reader, const  Fraction& scale)
1017+       {
1018+       if  (scale != Fraction (1 , 1 )) {
1019+             while  (reader.readNext () && reader.tokenType () != XmlReader::TokenType::EndDocument) {
1020+                   QString tag (reader.name ().toString ());
1021+                   int  len = reader.intAttribute (" len" 0 );
1022+                   if  (len && !TDuration (Fraction::fromTicks (len) * scale).isValid ())
1023+                         return  false ;
1024+                   if  (tag == " durationType" 
1025+                         if  (!TDuration (TDuration (reader.readElementText ()).fraction () * scale).isValid ())
1026+                               return  false ;
1027+                   }
1028+             }
1029+       return  true ;
1030+       }
1031+ 
1032+ inline  static  bool  canPasteStaff (const  QByteArray& mimeData, const  Fraction& scale)
1033+ {
1034+     XmlReader reader (mimeData);
1035+     return  canPasteStaff (reader, scale);
1036+ }
1037+ 
9851038// ---------------------------------------------------------
9861039//    cmdPaste
9871040// ---------------------------------------------------------
@@ -1002,45 +1055,33 @@ void Score::cmdPaste(const QMimeData* ms, MuseScoreView* view, Fraction scale)
10021055
10031056            if  (!el)
10041057                  return ;
1058+             duration *= scale;
1059+             if  (!TDuration (duration).isValid ())
1060+                 return ;
10051061
10061062            QList<Element*> els;
10071063            if  (_selection.isSingle ())
10081064                  els.append (_selection.element ());
10091065            else 
10101066                  els.append (_selection.elements ());
1011- 
1067+             Element* nel =  0 ; 
10121068            for  (Element* target : els) {
10131069                  el->setTrack (target->track ());
1014-                   Element* nel = el->clone ();
10151070                  addRefresh (target->abbox ());   //  layout() ?!
10161071                  EditData ddata (view);
10171072                  ddata.view         = view;
1018-                   ddata.dropElement  = nel ;
1073+                   ddata.dropElement  = el. get () ;
10191074                  if  (target->acceptDrop (ddata)) {
1020-                         if  (el->isNote ()) {
1021-                               //  dropping a note replaces and invalidates the target,
1022-                               //  so we need to deselect it
1023-                               ElementType targetType = target->type ();
1024-                               deselect (target);
1025- 
1026-                               //  perform the drop
1027-                               target->drop (ddata);
1028- 
1029-                               //  if the target is a rest rather than a note,
1030-                               //  a new note is generated, and nel becomes invalid as well
1031-                               //  (ChordRest::drop() will select it for us)
1032-                               if  (targetType == ElementType::NOTE)
1033-                                     select (nel);
1075+                         if  (!el->isNote () || (target = prepareTarget (target, toNote (el.get ()), duration))) {
1076+                               ddata.dropElement  = nel = el->clone ();
1077+                               Element* dropped = target->drop (ddata);
1078+                               if  (dropped)
1079+                                     nel = dropped;
10341080                              }
1035-                         else  {
1036-                               target->drop (ddata);
1037-                               }
1038-                         if  (_selection.element ())
1039-                               addRefresh (_selection.element ()->abbox ());
10401081                        }
1041-                   else 
1042-                         delete  nel;
10431082                  }
1083+             if  (nel)
1084+                   select (nel);
10441085            }
10451086      else  if  ((_selection.isRange () || _selection.isList ()) && ms->hasFormat (mimeStaffListFormat)) {
10461087            ChordRest* cr = 0 ;
@@ -1069,10 +1110,12 @@ void Score::cmdPaste(const QMimeData* ms, MuseScoreView* view, Fraction scale)
10691110                  QByteArray data (ms->data (mimeStaffListFormat));
10701111                  if  (MScore::debugMode)
10711112                        qDebug (" paste <%s>" data ());
1072-                   XmlReader e (data);
1073-                   e.setPasteMode (true );
1074-                   if  (!pasteStaff (e, cr->segment (), cr->staffIdx (), scale))
1075-                         return ;
1113+                   if  (canPasteStaff (data, scale)) {
1114+                         XmlReader e (data);
1115+                         e.setPasteMode (true );
1116+                         if  (!pasteStaff (e, cr->segment (), cr->staffIdx (), scale))
1117+                             return ;
1118+                         }
10761119                  }
10771120            }
10781121      else  if  (ms->hasFormat (mimeSymbolListFormat)) {
0 commit comments