diff --git a/src/libs/core/score/tmeasureobject.cpp b/src/libs/core/score/tmeasureobject.cpp
index 91f38a359d8cc12a6f7a6e3f428d5a36145883e4..fe54db3460a8ddd36de087635d1f745aa8cd04d1 100644
--- a/src/libs/core/score/tmeasureobject.cpp
+++ b/src/libs/core/score/tmeasureobject.cpp
@@ -56,7 +56,7 @@ void TmeasureObject::setStaff(TstaffObject* st) {
 
 void TmeasureObject::appendNewNotes(int segmentId, int count) {
   // so far we are sure there is enough space for whole note list in this measure
-//   qDebug() << debug() << "append" << count << "note(s)";
+//   qDebug() << debug() << "append" << count << "note(s) from" << segmentId;
   for (int n = segmentId; n < segmentId + count; ++n)
     m_notes.append(m_score->noteSegment(n));
   updateRhythmicGroups();
diff --git a/src/libs/core/score/tnoteobject.cpp b/src/libs/core/score/tnoteobject.cpp
index 982956d4e3bee33093a6379766b67b7ea59d0a99..e18691a42d6de85945903198fb6be3930d50be52 100644
--- a/src/libs/core/score/tnoteobject.cpp
+++ b/src/libs/core/score/tnoteobject.cpp
@@ -113,6 +113,14 @@ TnoteObject::~TnoteObject() {
 }
 
 
+void TnoteObject::setStaff(TstaffObject* staffObj) {
+  if (staffObj != m_staff) {
+    m_staff = staffObj;
+    setParentItem(m_staff->staffItem());
+  }
+}
+
+
 void TnoteObject::setMeasure(TmeasureObject* m) {
   m_measure = m;
 }
diff --git a/src/libs/core/score/tnoteobject.h b/src/libs/core/score/tnoteobject.h
index 0fbf281b31601e08707f6219934b2409026c3739..9871abd807394dee4062e87c7af2ee487dd1349c 100644
--- a/src/libs/core/score/tnoteobject.h
+++ b/src/libs/core/score/tnoteobject.h
@@ -44,6 +44,7 @@ public:
   ~TnoteObject();
 
   TstaffObject* staff() const { return m_staff; }
+  void setStaff(TstaffObject* staffObj);
 
   TmeasureObject* measure() { return m_measure; }
   void setMeasure(TmeasureObject* m);
diff --git a/src/libs/core/score/tscoreobject.cpp b/src/libs/core/score/tscoreobject.cpp
index ce37e57d128c2ecb906a965e65632c28d95feb89..4e573b72dc4181cd41df1a78a30fbf00d35d1278 100644
--- a/src/libs/core/score/tscoreobject.cpp
+++ b/src/libs/core/score/tscoreobject.cpp
@@ -27,7 +27,7 @@
 #include <QtCore/qdebug.h>
 #include "checktime.h"
 
-#define MIN_STAFF_FACTOR (1.2) // if TstaffObject::gapFactor is less than this value - new staff is necessary
+// #define MIN_STAFF_FACTOR (1.2) // if TstaffObject::gapFactor is less than this value - new staff is necessary
 
 
 TscoreObject::TscoreObject(QObject* parent) :
@@ -78,21 +78,15 @@ CHECKTIME (
   auto lastMeasure = m_measures.last();
   if (lastMeasure->free() == 0) { // new measure is needed
     lastMeasure = new TmeasureObject(m_measures.count(), this);
-    auto lastSt = lastStaff();
-    if (lastSt->gapFactor() < MIN_STAFF_FACTOR) { // and new staff is needed as well
-      emit staffCreate();
-      lastSt = lastStaff();
-    }
-    lastStaff()->appendMeasure(lastMeasure);
     m_measures << lastMeasure;
+    lastStaff()->appendMeasure(lastMeasure);
   }
   int noteDur = n.duration();
   if (noteDur > lastMeasure->free()) { // split note that is adding
-    int leftDuration = noteDur - lastMeasure->free();
-      QList<Tnote> notesToCurrent;
-      QList<Tnote> notesToNext;
+      int leftDuration = noteDur - lastMeasure->free();
       int lastNoteId = m_segments.count();
 
+      QList<Tnote> notesToCurrent;
       solveList(n, lastMeasure->free(), notesToCurrent); // solve free duration in current measure
       if (notesToCurrent.isEmpty())
           qDebug() << "[TscoreObject] can't resolve duration of" << lastMeasure->free();
@@ -101,6 +95,7 @@ CHECKTIME (
           lastMeasure->appendNewNotes(lastNoteId, notesToCurrent.count());
       }
 
+      QList<Tnote> notesToNext;
       solveList(n, leftDuration, notesToNext); // solve remaining duration for the next measure
       lastNoteId = m_segments.count(); // update id of the last note segment
       if (notesToNext.isEmpty())
@@ -108,20 +103,14 @@ CHECKTIME (
       else {
           appendNoteList(notesToNext);
           auto newLastMeasure = new TmeasureObject(m_measures.count(), this); // add a new measure
-          auto lastSt = lastStaff();
-          if (lastSt->gapFactor() < 1.2) {
-            emit staffCreate();
-            lastSt = lastStaff();
-          }
-          lastSt->appendMeasure(newLastMeasure);
           m_measures << newLastMeasure;
+          lastStaff()->appendMeasure(newLastMeasure);
           newLastMeasure->appendNewNotes(lastNoteId, notesToNext.count());
       }
-  } else { // just add new note to the measure
+  } else { // just add new note to the last measure
       m_notes << n;
       int lastNoteId = m_segments.count();
-      auto newSeg = new TnotePair(lastNoteId, &m_notes.last());
-      m_segments << newSeg;
+      m_segments << new TnotePair(lastNoteId, &m_notes.last());
       lastMeasure->appendNewNotes(lastNoteId, 1);
   }
 
@@ -182,7 +171,10 @@ int TscoreObject::meterToInt() { return static_cast<int>(m_meter->meter()); }
 
 
 qreal TscoreObject::stavesHeight() {
-  return m_staves.isEmpty() ? 0.0 : lastStaff()->staffItem()->y() + lastStaff()->staffItem()->height() * lastStaff()->scale();
+  if (m_staves.isEmpty())
+    return 0.0;
+  auto last = lastStaff();
+  return last->staffItem()->y() + last->staffItem()->height() * last->scale();
 }
 
 
@@ -194,6 +186,7 @@ void TscoreObject::addStaff(TstaffObject* st) {
   m_staves.append(st);
   if (m_staves.count() == 1) // initialize first measure of first staff
     st->appendMeasure(m_measures.first());
+  // next staves position ca be set only when staffItem is set, see TstaffObject::setStaffItem() then
   connect(st, &TstaffObject::hiNotePosChanged, [=](int staffNr, qreal offset){
     for (int i = staffNr; i < m_staves.size(); ++i) // move every staff about offset
       m_staves[i]->staffItem()->setY(m_staves[i]->staffItem()->y() + offset);
@@ -209,6 +202,27 @@ void TscoreObject::addStaff(TstaffObject* st) {
 }
 
 
+void TscoreObject::shiftMeasures(int firstId, int count) {
+  qDebug() << "[TscoreObject] shifting" << count << "measure(s) from" << firstId;
+  auto sourceStaff = m_measures[firstId]->staff();
+  TstaffObject* targetStaff = nullptr;
+  if (sourceStaff == lastStaff()) { // create new staff to shift measure(s) there
+      emit staffCreate();
+      targetStaff = lastStaff();
+  } else
+      targetStaff = m_staves[sourceStaff->number()];
+
+  for (int m = firstId; m < firstId + count; ++m) {
+    auto meas = m_measures[m];
+    for (int n = 0; n < meas->noteCount(); ++n)
+      meas->note(n)->object()->setStaff(targetStaff);
+
+    sourceStaff->takeMeasure(meas->number() - sourceStaff->firstMeasureNr());
+    targetStaff->appendMeasure(meas);
+  }
+  targetStaff->refresh();
+}
+
 //#################################################################################################
 //###################              PRIVATE             ############################################
 //#################################################################################################
diff --git a/src/libs/core/score/tscoreobject.h b/src/libs/core/score/tscoreobject.h
index bfa482eea976c8756bf06a46eac562be024c9c53..9ef6a109640c624c590f1e3bc424c0b7f9a44532 100644
--- a/src/libs/core/score/tscoreobject.h
+++ b/src/libs/core/score/tscoreobject.h
@@ -116,7 +116,15 @@ public:
 
 signals:
   void meterChanged();
+
+      /**
+       * Asks Score.qml about create new staff
+       */
   void staffCreate();
+  
+      /**
+       * Informs Score.qml that content widget height has to be adjusted to all staves height
+       */
   void stavesHeightChanged();
 
 protected:
@@ -124,6 +132,13 @@ protected:
 
   TclefOffset clefOffset() const { return m_clefOffset; }
 
+      /**
+       * Shifts @p count measures starting from @p firstId among all score measures.
+       * It detects the staff the measure belongs to and finds the next one or creates a new staff if not exists.
+       * Also it manages ownership of initial (source) staff shifted notes and sets parent of every such note to target staff.
+       */
+  void shiftMeasures(int firstId, int count = 1);
+
 private:
       /**
        * Appends notes to @p m_notes list, creates corresponding @p TnotePair
diff --git a/src/libs/core/score/tstaffobject.cpp b/src/libs/core/score/tstaffobject.cpp
index c6c4b0cc2ed3bf4fa9c7ee90c02cb4a45dea3a9f..404aabc12bf79d09545bc1e28eb2c8c12254b4df 100644
--- a/src/libs/core/score/tstaffobject.cpp
+++ b/src/libs/core/score/tstaffobject.cpp
@@ -31,20 +31,18 @@ TstaffObject::TstaffObject(QObject* parent) :
   m_score(nullptr),
   m_upperLine(16.0),
   m_staffItem(nullptr),
-  m_loNotePos(28.0), m_hiNotePos(12.0)
+  m_loNotePos(28.0), m_hiNotePos(8.0)
 {
 }
 
 
-TstaffObject::~TstaffObject() { 
-  qDebug() << debug() << "is going delete";
+TstaffObject::~TstaffObject() {
+  qDebug() << "[TstaffObject] is going delete";
 }
 
 
 void TstaffObject::setScore(TscoreObject* s) {
   m_score = s;
-  setParent(s);
-  qDebug() << debug() << this << "got a score parent" << s;
   m_score->addStaff(this);
 }
 
@@ -63,16 +61,15 @@ void TstaffObject::setUpperLine(qreal upLine) {
 
 void TstaffObject::setStaffItem(QQuickItem* si) {
   m_staffItem = si;
-  if (m_score->stavesCount() > 1) {
+  if (m_score->stavesCount() > 1) { // initial staff position, depends on lowest note in the previous staff
     auto prevStaff = m_score->staff(m_score->stavesCount() - 2);
-    m_staffItem->setY(prevStaff->staffItem()->y() + prevStaff->minHeight() * prevStaff->scale()); // scale of this staff is not set yet
+    m_staffItem->setY(prevStaff->staffItem()->y() + (prevStaff->loNotePos() - hiNotePos()) * prevStaff->scale()); // scale of this staff is not set yet
   }
-  qDebug() << debug() << "set staff item to" << m_staffItem;
 }
 
 
 int TstaffObject::firstMeasureNr() {
-  return m_measures.first()->number();
+  return m_measures.empty() ? 0 : m_measures.first()->number();
 }
 
 
@@ -111,28 +108,38 @@ void TstaffObject::fit() {
   }
 
   qreal factor = 2.5;
-  qreal m_gapsSum = 0.0;
-  qreal m_allNotesWidth = 0.0;
+  qreal gapsSum = 0.0;
+  m_allNotesWidth = 0.0;
 
   for (int m = 0; m < m_measures.size(); ++m) {
     auto measure = m_measures[m];
     for (int n = 0; n < measure->noteCount(); ++n) {
       auto note = measure->note(n)->object();
-      m_gapsSum += note->rhythmFactor();
+      gapsSum += note->rhythmFactor();
       m_allNotesWidth += note->width();
-      if (n > 1) {
-        factor = (m_staffItem->width() - m_notesIndent - m_allNotesWidth - 1.0) / m_gapsSum;
-        //       if (factor < 1.0) { // shift current measure and the next ones
-        //         needShift = true;
-        //         break; // rest of the notes goes to the next staff
-        //       }
+      factor = (m_staffItem->width() - m_notesIndent - m_allNotesWidth - 1.0) / gapsSum;
+      if (factor < 0.8) { // shift current measure and the next ones
+        if (m == 0)
+            qDebug() << debug() << "!!!!!! Split this measure among staves !!!!!";
+        else {
+            for (int nn = n; nn >= 0; --nn) { // revert gapsSum and m_allNotesWidth to state at the end of the previous measure
+              auto revertNote = measure->note(nn)->object();
+              gapsSum -= revertNote->rhythmFactor();
+              m_allNotesWidth -= revertNote->width();
+            }
+            m_gapFactor = (m_staffItem->width() - m_notesIndent - m_allNotesWidth - 1.0) / gapsSum;  // allow factor bigger than 2.5
+            m_score->shiftMeasures(measure->number(), m_measures.count() - m);
+            updateNotesPos();
+            return;
+        }
+        break; // rest of the notes goes to the next staff
       }
     }
   }
 
   m_gapFactor = qBound(0.5, factor, 2.5); // notes in this staff are ready to positioning
   updateNotesPos();
-  qDebug() << debug() << "gap factor" << m_gapFactor << m_allNotesWidth << m_gapsSum;
+//   qDebug() << debug() << "gap factor" << m_gapFactor << "notes count" << lastMeasure()->last()->index() + 1;
 }
 
 
@@ -141,7 +148,8 @@ void TstaffObject::updateNotesPos(int startMeasure) {
   if (firstMeas->isEmpty())
     return;
 
-  qDebug() << debug() << "updating notes positions from" << startMeasure << "measure";
+  qDebug() << debug() << "updating notes positions from" << startMeasure << "measure" 
+            << "gap factor" << m_gapFactor << "notes count" << lastMeasure()->last()->index() + 1;
   TnoteObject* prevNote = nullptr;
   if (startMeasure == 0)
     firstMeas->first()->object()->setX(m_notesIndent);
@@ -178,9 +186,19 @@ void TstaffObject::checkNotesRange(bool doEmit) {
 void TstaffObject::appendMeasure(TmeasureObject* m) {
   m->setStaff(this);
   m_measures << m;
+  if (m_measures.count() == 1)
+    emit firstMeasureNrChanged();
 }
 
 
+void TstaffObject::takeMeasure(int id) {
+  m_measures.removeAt(id);
+  if (id == 0)
+    emit firstMeasureNrChanged();
+}
+
+
+
 //#################################################################################################
 //###################              PRIVATE             ############################################
 //#################################################################################################
diff --git a/src/libs/core/score/tstaffobject.h b/src/libs/core/score/tstaffobject.h
index 473b9737074d7576d42820ab84cf72017b6b81ae..b8ac45e22d7971625ea882ac2289f3c2fdfa5809 100644
--- a/src/libs/core/score/tstaffobject.h
+++ b/src/libs/core/score/tstaffobject.h
@@ -33,7 +33,7 @@ class Tnote;
 
 
 /**
- * 
+ * @class TstaffObject is C++ logic of Staff.qml
  */
 class NOOTKACORE_EXPORT  TstaffObject : public QObject
 {
@@ -106,6 +106,11 @@ public:
        */
   qreal minHeight() const { return m_loNotePos - (number() == 0 ? 0.0 : m_hiNotePos); }
 
+      /**
+       * Width of all notes on the staff
+       */
+  qreal allNotesWidth() { return m_allNotesWidth; }
+
       /**
        * Scaling factor of the staff
        */
@@ -133,6 +138,7 @@ protected:
   void checkNotesRange(bool doEmit = true);
 
   void appendMeasure(TmeasureObject* m);
+  void takeMeasure(int id);
 
 private:
   void findLowestNote(); /**< Checks all Y positions of staff notes to find lowest one */
@@ -146,6 +152,7 @@ private:
   qreal                          m_notesIndent;
   qreal                          m_gapFactor;
   qreal                          m_loNotePos, m_hiNotePos;
+  qreal                          m_allNotesWidth = 0.0;
 };
 
 #endif // TSTAFFOBJECT_H
diff --git a/src/qml/score/Score.qml b/src/qml/score/Score.qml
index c1678564fd487e7677ab3985dae1fc43027d56cb..dcf57b8c1c64cda5c79ac67c253af89edf50050a 100644
--- a/src/qml/score/Score.qml
+++ b/src/qml/score/Score.qml
@@ -37,6 +37,7 @@ Flickable {
       score.contentY = score.contentHeight - score.height
       lastStaff.keySignature.onKeySignatureChanged.connect(setKeySignature)
     }
+    onStavesHeightChanged: score.contentHeight = Math.max(stavesHeight, score.height)
   }
 
   property alias scale: staff0.scale
@@ -61,7 +62,7 @@ Flickable {
   width: parent.width
 
   contentWidth: score.width
-  contentHeight: scoreObj.stavesHeight
+//   contentHeight: Math.max(scoreObj.stavesHeight, score.height)
 
   Rectangle {
     id: bgRect