LCOV - code coverage report
Current view: top level - src/engraving/accessibility - accessibleroot.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 6.4 % 110 7
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : #include "accessibleroot.h"
      23              : 
      24              : #include "../dom/score.h"
      25              : #include "../dom/staff.h"
      26              : #include "../dom/part.h"
      27              : #include "../dom/segment.h"
      28              : 
      29              : #include "log.h"
      30              : #include "translation.h"
      31              : 
      32              : using namespace mu::engraving;
      33              : using namespace muse::accessibility;
      34              : 
      35         4668 : AccessibleRoot::AccessibleRoot(RootItem* e, Role role)
      36         4668 :     : AccessibleItem(e, role)
      37              : {
      38         4668 : }
      39              : 
      40         4190 : AccessibleRoot::~AccessibleRoot()
      41              : {
      42         4190 :     if (m_registred && accessibilityController()) {
      43            0 :         accessibilityController()->unreg(this);
      44            0 :         m_registred = false;
      45              :     }
      46              : 
      47         4190 :     m_element = nullptr;
      48         4190 : }
      49              : 
      50            0 : void AccessibleRoot::setFocusedElement(AccessibleItemPtr e, bool voiceStaffInfoChange)
      51              : {
      52            0 :     if (!m_enabled) {
      53            0 :         return; // User is outside the score panel (e.g. in the Braille panel).
      54              :     }
      55              : 
      56            0 :     AccessibleItemWeakPtr old = m_focusedElement;
      57            0 :     updateStaffInfo(e, old, voiceStaffInfoChange);
      58              : 
      59            0 :     if (auto oldItem = old.lock()) {
      60            0 :         oldItem->notifyAboutFocus(false);
      61            0 :     }
      62              : 
      63            0 :     m_focusedElement = e;
      64            0 :     if (auto newItem = m_focusedElement.lock()) {
      65            0 :         newItem->notifyAboutFocus(true);
      66            0 :     }
      67            0 : }
      68              : 
      69            0 : AccessibleItemWeakPtr AccessibleRoot::focusedElement() const
      70              : {
      71            0 :     return m_focusedElement;
      72              : }
      73              : 
      74            0 : void AccessibleRoot::notifyAboutFocusedElementNameChanged()
      75              : {
      76            0 :     m_staffInfo = "";
      77              : 
      78            0 :     if (auto focusedElement = m_focusedElement.lock()) {
      79            0 :         focusedElement->accessiblePropertyChanged().send(IAccessible::Property::Name, muse::Val());
      80            0 :     }
      81            0 : }
      82              : 
      83            0 : RectF AccessibleRoot::toScreenRect(const RectF& rect, bool* ok) const
      84              : {
      85            0 :     RectF result;
      86            0 :     if (m_accessibleMapToScreenFunc) {
      87            0 :         result = m_accessibleMapToScreenFunc(rect);
      88              :     }
      89              : 
      90            0 :     if (ok) {
      91            0 :         *ok = m_accessibleMapToScreenFunc != nullptr;
      92              :     }
      93              : 
      94            0 :     return result;
      95              : }
      96              : 
      97            0 : const IAccessible* AccessibleRoot::accessibleParent() const
      98              : {
      99            0 :     return accessibilityController()->accessibleRoot();
     100              : }
     101              : 
     102            0 : IAccessible::Role AccessibleRoot::accessibleRole() const
     103              : {
     104            0 :     return IAccessible::Panel;
     105              : }
     106              : 
     107            0 : QString AccessibleRoot::accessibleName() const
     108              : {
     109            0 :     return muse::qtrc("engraving", "Score") + " " + element()->score()->name();
     110              : }
     111              : 
     112            0 : bool AccessibleRoot::enabled() const
     113              : {
     114            0 :     return m_enabled;
     115              : }
     116              : 
     117            0 : void AccessibleRoot::setEnabled(bool enabled)
     118              : {
     119            0 :     m_enabled = enabled;
     120            0 : }
     121              : 
     122            0 : QString AccessibleRoot::staffInfo() const
     123              : {
     124            0 :     return m_staffInfo;
     125              : }
     126              : 
     127            0 : void AccessibleRoot::updateStaffInfo(const AccessibleItemWeakPtr newAccessibleItem, const AccessibleItemWeakPtr oldAccessibleItem,
     128              :                                      bool voiceStaffInfoChange)
     129              : {
     130            0 :     m_staffInfo = "";
     131              : 
     132            0 :     if (!voiceStaffInfoChange) {
     133            0 :         return;
     134              :     }
     135              : 
     136            0 :     AccessibleItemPtr newItem = newAccessibleItem.lock();
     137            0 :     AccessibleItemPtr oldItem = oldAccessibleItem.lock();
     138              : 
     139            0 :     if (newItem && newItem->element()->hasStaff()) {
     140            0 :         staff_idx_t newStaffIdx = newItem->element()->staffIdx();
     141            0 :         staff_idx_t oldStaffIdx = oldItem ? oldItem->element()->staffIdx() : muse::nidx;
     142              : 
     143            0 :         if (newStaffIdx != oldStaffIdx) {
     144            0 :             auto element = newItem->element();
     145            0 :             QString staff = muse::qtrc("engraving", "Staff %1").arg(QString::number(element->staffIdx() + 1));
     146              : 
     147            0 :             const Part* origin = element->originPart();
     148            0 :             QString staffName = origin ? origin->longName(element->tick()).toQString() : QString();
     149            0 :             if (staffName.isEmpty() && origin) {
     150            0 :                 staffName = origin->partName().toQString();
     151              :             }
     152              : 
     153            0 :             if (staffName.isEmpty()) {
     154            0 :                 m_staffInfo = staff;
     155              :             } else {
     156            0 :                 m_staffInfo = QString("%2 (%3)").arg(staff, staffName);
     157              :             }
     158            0 :         }
     159              :     }
     160            0 : }
     161              : 
     162            0 : void AccessibleRoot::setMapToScreenFunc(const AccessibleMapToScreenFunc& func)
     163              : {
     164            0 :     m_accessibleMapToScreenFunc = func;
     165            0 : }
     166              : 
     167            0 : bool AccessibleRoot::isRangeSelection() const
     168              : {
     169            0 :     return element()->score()->selection().isRange();
     170              : }
     171              : 
     172            0 : QString AccessibleRoot::rangeSelectionInfo()
     173              : {
     174            0 :     Score* score = element()->score();
     175            0 :     Selection selection = score->selection();
     176            0 :     Segment* startSegment = selection.startSegment();
     177            0 :     Segment* endSegment = selection.endSegment();
     178              : 
     179            0 :     if (endSegment) {
     180              :         // Make end beat match status bar text
     181            0 :         endSegment = endSegment->prev1(SegmentType::ChordRest);
     182              :     }
     183              : 
     184            0 :     IF_ASSERT_FAILED(selection.isRange() && startSegment && endSegment) {
     185            0 :         return QString();
     186              :     }
     187              : 
     188            0 :     String startBarBeat = startSegment->formatBarsAndBeats();
     189            0 :     String endBarBeat = endSegment->formatBarsAndBeats();
     190              : 
     191            0 :     startBarBeat.remove(u';'); // Too many pauses in speech
     192            0 :     endBarBeat.remove(u';');
     193              : 
     194            0 :     QString staffInstrument1, staffInstrument2;
     195            0 :     staff_idx_t startStaff = selection.staffStart();
     196            0 :     staff_idx_t endStaff = selection.staffEnd() - 1;
     197              : 
     198            0 :     if (startStaff != endStaff) {
     199            0 :         const Staff* staff1 = score->staff(startStaff);
     200            0 :         const Staff* staff2 = score->staff(endStaff);
     201            0 :         const Part* part1 = staff1 ? staff1->originPart(startSegment->tick()) : nullptr;
     202            0 :         const Part* part2 = staff2 ? staff2->originPart(endSegment->tick()) : nullptr;
     203            0 :         if (staff1 && staff2 && part1 && part2) {
     204            0 :             staffInstrument1 = muse::qtrc("engraving", "Staff %1 (%2)")
     205            0 :                                .arg(QString::number(startStaff + 1))
     206            0 :                                .arg(staff1 ? part1->partName().toQString() : "");
     207            0 :             staffInstrument2 = muse::qtrc("engraving", "Staff %1 (%2)")
     208            0 :                                .arg(QString::number(endStaff + 1))
     209            0 :                                .arg(staff2 ? part2->partName().toQString() : "");
     210              :         }
     211              :     }
     212              : 
     213            0 :     return muse::qtrc("engraving", "Range selection starts %1%2 ends %3%4")
     214            0 :            .arg(startBarBeat)
     215            0 :            .arg(!staffInstrument1.isEmpty() ? (" " + staffInstrument1) : "")
     216            0 :            .arg(endBarBeat)
     217            0 :            .arg(!staffInstrument2.isEmpty() ? (" " + staffInstrument2) : "");
     218            0 : }
        

Generated by: LCOV version 2.0-1