From adac9f973d2544df215e4af3b824e62abecb9856 Mon Sep 17 00:00:00 2001
From: SeeLook <945374+SeeLook@users.noreply.github.com>
Date: Fri, 2 Feb 2018 21:11:38 +0100
Subject: [PATCH] Separate beams for each staff of grand one, stem lenght and
 direction adjusted to lower staff when necessary.

---
 changes                                |  1 +
 src/libs/core/score/tbeamobject.cpp    | 14 +++++++++++---
 src/libs/core/score/tmeasureobject.cpp |  4 +++-
 src/libs/core/score/tnoteitem.cpp      | 17 ++++++++++-------
 src/libs/core/score/tstaffitem.cpp     |  5 +++++
 src/libs/core/score/tstaffitem.h       |  2 ++
 6 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/changes b/changes
index 22903b8d4..12dbb33d3 100644
--- a/changes
+++ b/changes
@@ -1,4 +1,5 @@
 1.5.2 alpha3
+     - extended grand staff, beaming notes on every staff separately
      - score supports bowing symbols, read them from XML
      - improved level creator
 
diff --git a/src/libs/core/score/tbeamobject.cpp b/src/libs/core/score/tbeamobject.cpp
index 59b059398..db5644db3 100644
--- a/src/libs/core/score/tbeamobject.cpp
+++ b/src/libs/core/score/tbeamobject.cpp
@@ -118,7 +118,8 @@ void TbeamObject::prepareBeam() {
   bool stemsUpPossible = true;
   qreal hiNote = 99.0, loNote = 0.0;
   for (TnotePair* np : qAsConst(m_notes)) {
-    stemDirStrength += np->item()->notePosY() - (m_measure->staff()->upperLine() + 4.0);
+    stemDirStrength += np->item()->notePosY() - (m_measure->staff()->upperLine()
+              + (m_measure->score()->isPianoStaff() && np->item()->notePosY() > m_measure->staff()->upperLine() + 13.0 ? 26.0 : 4.0));
     if (np->item()->notePosY() < MIN_STEM_HEIGHT)
       stemsUpPossible = false;
     hiNote = qMin(hiNote, np->item()->notePosY());
@@ -129,8 +130,15 @@ void TbeamObject::prepareBeam() {
   if (stemDirStrength < 0)
     allStemsDown = true; // stems down are always possible
   qreal stemTop = allStemsDown ? loNote + minStemHeight : hiNote - minStemHeight;
-  if ((allStemsDown && stemTop < m_measure->staff()->upperLine() + 4.0) || (!allStemsDown && stemTop > m_measure->staff()->upperLine() + 4.0))
-    stemTop = m_measure->staff()->upperLine() + 4.0; // keep beam on staff middle line
+  if (m_measure->score()->isPianoStaff() && !first()->note()->onUpperStaff()) { // when note lays on the lower staff
+      qreal lowerMidLine = m_measure->staff()->upperLine() + 26.0;
+      if ((allStemsDown && stemTop < lowerMidLine) || (!allStemsDown && stemTop > lowerMidLine))
+        stemTop = lowerMidLine; // keep beam on the lower staff middle line
+  } else {
+      qreal upperMidLine = m_measure->staff()->upperLine() + 4.0;
+      if ((allStemsDown && stemTop < upperMidLine) || (!allStemsDown && stemTop > upperMidLine))
+        stemTop = upperMidLine; // keep beam on staff middle line
+  }
   for (TnotePair* np : qAsConst(m_notes)) {
     np->note()->rtm.setStemDown(allStemsDown);
     np->addChange(TnotePair::e_stemDirChanged);
diff --git a/src/libs/core/score/tmeasureobject.cpp b/src/libs/core/score/tmeasureobject.cpp
index 5268d0406..0b3ad18af 100644
--- a/src/libs/core/score/tmeasureobject.cpp
+++ b/src/libs/core/score/tmeasureobject.cpp
@@ -243,7 +243,9 @@ int TmeasureObject::beamGroup(int segmentId) {
     auto prevSeg = m_notes[segId - 1];
     if (!noteSeg->note()->isRest() && !prevSeg->note()->isRest() // not a rest
       && noteSeg->note()->rhythm() > Trhythm::Quarter // sixteenth or eighth
-      && prevSeg->note()->rhythm() > Trhythm::Quarter)
+      && prevSeg->note()->rhythm() > Trhythm::Quarter
+      && (!m_score->isPianoStaff() || noteSeg->note()->onUpperStaff() == prevSeg->note()->onUpperStaff())
+    )
     {
         if (prevSeg->note()->rtm.beam() == Trhythm::e_noBeam) // start beam group
           prevSeg->setBeam(new TbeamObject(prevSeg, this));
diff --git a/src/libs/core/score/tnoteitem.cpp b/src/libs/core/score/tnoteitem.cpp
index 4f4418f11..17625a58b 100644
--- a/src/libs/core/score/tnoteitem.cpp
+++ b/src/libs/core/score/tnoteitem.cpp
@@ -210,7 +210,8 @@ void TnoteItem::setNote(const Tnote& n) {
   bool updateHead = n.rhythm() != m_note->rhythm() || n.isRest() != m_note->isRest() || n.hasDot() != m_note->hasDot();
   bool fixBeam = n.isRest() != m_note->isRest();
   bool updateStem = updateHead || fixBeam || ((n.rtm.beam() != Trhythm::e_noBeam) != (m_note->rtm.beam() != Trhythm::e_noBeam))
-        || (n.rtm.stemDown() != m_note->rtm.stemDown() || m_stem->height() != m_stemHeight);
+        || (n.rtm.stemDown() != m_note->rtm.stemDown() || m_stem->height() != m_stemHeight) 
+        || n.onUpperStaff() != m_note->onUpperStaff();
   bool updateTie = n.rtm.tie() != m_note->rtm.tie();
 
   *m_note = n;
@@ -234,7 +235,7 @@ void TnoteItem::setNote(const Tnote& n) {
   else {
     if (m_note->isValid()) {
         m_notePosY = staff()->score()->clefOffset().total() + staff()->upperLine() - (n.octave() * 7 + (n.note() - 1));
-        if (staff()->score()->isPianoStaff()) {
+        if (staff()->isPianoStaff()) {
           if (m_note->onUpperStaff()) {
               if (m_notePosY > staff()->upperLine() + 13.0)
                 m_notePosY += 10.0;
@@ -326,7 +327,7 @@ void TnoteItem::setHeight(qreal hh) {
       m_upLines[l]->setY(2 * (l + 1) - 0.1);
       m_loLines[l]->setY(staff()->upperLine() + 10.0 + 2 * l - 0.1);
     }
-    if (staff()->score()->isPianoStaff()) {
+    if (staff()->isPianoStaff()) {
       if (m_underLoLines.isEmpty()) {
         m_staff->score()->component()->setData("import QtQuick 2.9; Rectangle {}", QUrl());
         for (int l = 0; l < 2; ++l) {
@@ -783,8 +784,10 @@ void TnoteItem::updateTieScale() {
 void TnoteItem::checkStem() {
   if (m_notePosY && !m_note->isRest() && m_note->rhythm() > Trhythm::Whole ) {
       if (m_note->rtm.beam() == Trhythm::e_noBeam) {
-          m_note->rtm.setStemDown(m_notePosY < staff()->upperLine() + 4.0);
-          m_stem->setHeight(qMax(STEM_HEIGHT, qAbs(m_notePosY - (staff()->upperLine() + 4.0))));
+          m_note->rtm.setStemDown(m_notePosY < staff()->upperLine() + 4.0
+                                  || (staff()->isPianoStaff() && m_notePosY > staff()->upperLine() + 13.0 && m_notePosY < staff()->upperLine() + 26.0));
+          m_stem->setHeight(qMax(STEM_HEIGHT, qAbs(m_notePosY
+                            - (staff()->upperLine() + (staff()->isPianoStaff() && m_notePosY > staff()->upperLine() + 13.0 ? 26.0 : 4.0)))));
           QString flagText = getFlagText();
           m_flag->setProperty("text", flagText);
           if (!flagText.isEmpty())
@@ -834,11 +837,11 @@ void TnoteItem::updateNamePos() {
  */
 void TnoteItem::checkAddLinesVisibility() {
   bool v = m_head->isVisible() && !m_note->isRest();
-  bool betweenStaves = staff()->score()->isPianoStaff() &&  m_notePosY >= staff()->upperLine() + 10.0 && m_notePosY < staff()->upperLine() + 21.0;
+  bool betweenStaves = staff()->isPianoStaff() &&  m_notePosY >= staff()->upperLine() + 10.0 && m_notePosY < staff()->upperLine() + 21.0;
   for (int i = 0; i < 7; ++i) {
     m_upLines[i]->setVisible(v && m_notePosY > 0.0 && i >= qFloor((m_notePosY - 1.0) / 2.0));
     qreal upp1 = staff()->upperLine() + 10.0 + i * 2;
-    if (staff()->score()->isPianoStaff()) {
+    if (staff()->isPianoStaff()) {
         if (m_notePosY < staff()->upperLine() + 14.0)
           m_loLines[i]->setVisible(v && betweenStaves && m_notePosY >= upp1 && m_notePosY < staff()->upperLine() + 14.0);
         else
diff --git a/src/libs/core/score/tstaffitem.cpp b/src/libs/core/score/tstaffitem.cpp
index 85199dce0..251ff0219 100644
--- a/src/libs/core/score/tstaffitem.cpp
+++ b/src/libs/core/score/tstaffitem.cpp
@@ -101,6 +101,11 @@ void TstaffItem::setNotesIndent(qreal ni) {
 }
 
 
+bool TstaffItem::isPianoStaff() const {
+  return m_scoreObj->isPianoStaff();
+}
+
+
 char TstaffItem::debug() {
   QTextStream o(stdout);
   o << "\033[01;34m[" << number() + 1 << " STAFF]\033[01;00m";
diff --git a/src/libs/core/score/tstaffitem.h b/src/libs/core/score/tstaffitem.h
index b1a95a168..ddb33854d 100644
--- a/src/libs/core/score/tstaffitem.h
+++ b/src/libs/core/score/tstaffitem.h
@@ -122,6 +122,8 @@ public:
 
   qreal gapsSum() const { return m_gapsSum; }
 
+  bool isPianoStaff() const;
+
       /**
        * Prints to std out debug info about this staff: [nr STAFF] in color
        */
-- 
GitLab