Description: Add Element::barbeat() and Element::accessibleBarbeat()
 These are const, and useful for determining the positions of elements
 within the score, generally; used by experiments/log-collisions.diff
 .
 Also fix some screenreader label mistakes.
 .
 For pre-3.1, backports commit 29cd62df329525da59d01a54796171076acc9eb1
 from upstream, to fix bad barbeat counting in cut time.
Author: mirabilos <m@mirbsd.org>
Forwarded: https://github.com/musescore/MuseScore/pull/5096

--- a/libmscore/element.cpp
+++ b/libmscore/element.cpp
@@ -60,6 +60,7 @@
 #include "rest.h"
 #include "score.h"
 #include "segment.h"
+#include "sig.h"
 #include "slur.h"
 #include "spacer.h"
 #include "staff.h"
@@ -1998,4 +1999,53 @@ bool Element::isUserModified() const
       return !visible() || !userOff().isNull() || (color() != MScore::defaultColor);
       }
 
+//---------------------------------------------------------
+//   barbeat
+//---------------------------------------------------------
+
+std::pair<int, float> Element::barbeat() const
+      {
+      int bar = 0;
+      int beat = 0;
+      int ticks = 0;
+      TimeSigMap* tsm = this->score()->sigmap();
+      const Element* p = this;
+      int ticksB = ticks_beat(tsm->timesig(0).timesig().denominator());
+      while(p && p->type() != Element::Type::SEGMENT && p->type() != Element::Type::MEASURE)
+            p = p->parent();
+
+      if (!p) {
+            return std::pair<int, float>(0, 0);
+            }
+      else if (p->type() == Element::Type::SEGMENT) {
+            const Segment* seg = static_cast<const Segment*>(p);
+            tsm->tickValues(seg->tick(), &bar, &beat, &ticks);
+            ticksB = ticks_beat(tsm->timesig(seg->tick()).timesig().denominator());
+            }
+      else if (p->type() == Element::Type::MEASURE) {
+            const Measure* m = static_cast<const Measure*>(p);
+            bar = m->no();
+            beat = -1;
+            ticks = 0;
+            }
+      return std::pair<int,float>(bar + 1, beat + 1 + ticks / static_cast<float>(ticksB));
+      }
+
+//---------------------------------------------------------
+//   accessibleBarbeat
+//---------------------------------------------------------
+
+QString Element::accessibleBarbeat() const
+      {
+      QString barsAndBeats = "";
+      std::pair<int, float>bar_beat = barbeat();
+      if (bar_beat.first) {
+            barsAndBeats += "; " + tr("Measure: %1").arg(QString::number(bar_beat.first));
+            if (bar_beat.second)
+                  barsAndBeats += "; " + tr("Beat: %1").arg(QString::number(bar_beat.second));
+            }
+      if (staffIdx() + 1)
+            barsAndBeats += "; " + tr("Staff: %1").arg(QString::number(staffIdx() + 1));
+      return barsAndBeats;
+      }
 }
--- a/libmscore/element.h
+++ b/libmscore/element.h
@@ -327,6 +327,8 @@ class Element : public QObject, public S
       Element* findMeasure();
 
       qreal spatium() const;
+      std::pair<int, float>barbeat() const;
+      QString accessibleBarbeat() const;
 
       bool selected() const                   { return _selected;   }
       virtual void setSelected(bool f)        { _selected = f;      }
--- a/libmscore/sig.cpp
+++ b/libmscore/sig.cpp
@@ -19,7 +19,7 @@ namespace Ms {
 //   ticks_beat
 //---------------------------------------------------------
 
-static int ticks_beat(int n)
+int ticks_beat(int n)
       {
       int m = (MScore::division * 4) / n;
       if ((MScore::division * 4) % n) {
--- a/libmscore/sig.h
+++ b/libmscore/sig.h
@@ -21,6 +21,8 @@ namespace Ms {
 class Xml;
 class XmlReader;
 
+int ticks_beat(int n);
+
 //-------------------------------------------------------------------
 //   BeatType
 //-------------------------------------------------------------------
--- a/mscore/scoreaccessibility.cpp
+++ b/mscore/scoreaccessibility.cpp
@@ -110,8 +110,8 @@ void ScoreAccessibility::currentInfoChan
             std::pair<int, float> bar_beat;
             if (el->isSpanner()){
                   Spanner* s = static_cast<Spanner*>(el);
-                  bar_beat = barbeat(s->startSegment());
-                  barsAndBeats += tr("Start Measure: %1; Start Beat: %2").arg(QString::number(bar_beat.first)).arg(QString::number(bar_beat.second));
+                  bar_beat = s->startSegment()->barbeat();
+                  barsAndBeats += " " + tr("Start Measure: %1; Start Beat: %2").arg(QString::number(bar_beat.first)).arg(QString::number(bar_beat.second));
                   Segment* seg = s->endSegment();
                   if(!seg)
                         seg = score->lastSegment()->prev1MM(Segment::Type::ChordRest);
@@ -121,11 +121,11 @@ void ScoreAccessibility::currentInfoChan
                       s->type() != Element::Type::TIE                                                )
                         seg = seg->prev1MM(Segment::Type::ChordRest);
 
-                  bar_beat = barbeat(seg);
+                  bar_beat = seg->barbeat();
                   barsAndBeats += "; " + tr("End Measure: %1; End Beat: %2").arg(QString::number(bar_beat.first)).arg(QString::number(bar_beat.second));
                   }
             else {
-                  std::pair<int, float>bar_beat = barbeat(el);
+                  std::pair<int, float>bar_beat = el->barbeat();
                   if (bar_beat.first) {
                         barsAndBeats += " " + tr("Measure: %1").arg(QString::number(bar_beat.first));
                         if (bar_beat.second)
@@ -135,12 +135,12 @@ void ScoreAccessibility::currentInfoChan
 
             QString rez = e->accessibleInfo();
             if (!barsAndBeats.isEmpty())
-                  rez += "; " + barsAndBeats;
+                  rez += ";" + barsAndBeats;
 
             QString staff = "";
             if (e->staffIdx() + 1) {
                   staff = tr("Staff %1").arg(QString::number(e->staffIdx() + 1));
-                  rez = QString("%1; %2").arg(rez).arg(staff);
+                  rez += "; " + tr("Staff: %1").arg(QString::number(e->staffIdx() + 1));
                   }
 
             statusBarLabel->setText(rez);
@@ -151,7 +151,7 @@ void ScoreAccessibility::currentInfoChan
             QString barsAndBeats = "";
             std::pair<int, float> bar_beat;
 
-            bar_beat = barbeat(score->selection().startSegment());
+            bar_beat = score->selection().startSegment()->barbeat();
             barsAndBeats += " " + tr("Start Measure: %1; Start Beat: %2").arg(QString::number(bar_beat.first)).arg(QString::number(bar_beat.second));
             Segment* endSegment = score->selection().endSegment();
 
@@ -160,7 +160,7 @@ void ScoreAccessibility::currentInfoChan
             else
                   endSegment = endSegment->prev1MM();
 
-            bar_beat = barbeat(endSegment);
+            bar_beat = endSegment->barbeat();
             barsAndBeats += " " + tr("End Measure: %1; End Beat: %2").arg(QString::number(bar_beat.first)).arg(QString::number(bar_beat.second));
             statusBarLabel->setText(tr("Range Selection") + barsAndBeats);
             score->setAccessibleInfo(tr("Range Selection") + barsAndBeats);
@@ -204,34 +204,4 @@ void ScoreAccessibility::updateAccessibi
       QAccessibleValueChangeEvent ev(obj, w->score()->accessibleInfo());
       QAccessible::updateAccessibility(&ev);
       }
-
-std::pair<int, float> ScoreAccessibility::barbeat(Element *e)
-      {
-      if (!e) {
-            return std::pair<int, float>(0, 0);
-            }
-
-      int bar = 0;
-      int beat = 0;
-      int ticks = 0;
-      TimeSigMap* tsm = e->score()->sigmap();
-      Element* p = e;
-      while(p && p->type() != Element::Type::SEGMENT && p->type() != Element::Type::MEASURE)
-            p = p->parent();
-
-      if (!p) {
-            return std::pair<int, float>(0, 0);
-            }
-      else if (p->type() == Element::Type::SEGMENT) {
-            Segment* seg = static_cast<Segment*>(p);
-            tsm->tickValues(seg->tick(), &bar, &beat, &ticks);
-            }
-      else if (p->type() == Element::Type::MEASURE) {
-            Measure* m = static_cast<Measure*>(p);
-            bar = m->no();
-            beat = -1;
-            ticks = 0;
-            }
-      return pair<int,float>(bar + 1, beat + 1 + ticks / static_cast<float>(MScore::division));
-      }
 }
--- a/mscore/scoreaccessibility.h
+++ b/mscore/scoreaccessibility.h
@@ -30,7 +30,6 @@ private:
       QMainWindow* mainWindow;
       QLabel* statusBarLabel;
       ScoreAccessibility(QMainWindow* statusBar);
-      std::pair<int, float>barbeat(Element* e);
 
 public:
       ~ScoreAccessibility();
