LCOV - code coverage report
Current view: top level - src/engraving/editing - editkeysig.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 90.8 % 65 59
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) 2025 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              : 
      23              : #include "editkeysig.h"
      24              : 
      25              : #include "dom/factory.h"
      26              : #include "dom/instrument.h"
      27              : #include "dom/keysig.h"
      28              : #include "dom/measure.h"
      29              : #include "dom/part.h"
      30              : #include "dom/score.h"
      31              : #include "dom/segment.h"
      32              : #include "dom/staff.h"
      33              : 
      34              : #include "addremoveelement.h"
      35              : #include "transaction/transaction.h"
      36              : #include "transpose.h"
      37              : 
      38              : #include "log.h"
      39              : 
      40              : using namespace mu::engraving;
      41              : 
      42              : //---------------------------------------------------------
      43              : //   ChangeKeySig
      44              : //---------------------------------------------------------
      45              : 
      46           46 : ChangeKeySig::ChangeKeySig(KeySig* k, KeySigEvent newKeySig, bool sc, bool addEvtToStaff)
      47           46 :     : keysig(k), ks(newKeySig), showCourtesy(sc), evtInStaff(addEvtToStaff)
      48           46 : {}
      49              : 
      50           78 : void ChangeKeySig::flip()
      51              : {
      52           78 :     Segment* segment = keysig->segment();
      53           78 :     Fraction tick = segment->tick();
      54           78 :     Staff* staff = keysig->staff();
      55              : 
      56           78 :     const bool curEvtInStaff = (staff->currentKeyTick(tick) == tick);
      57           78 :     KeySigEvent curKey = keysig->keySigEvent();
      58           78 :     const bool curShowCourtesy = keysig->showCourtesy();
      59              : 
      60           78 :     keysig->setKeySigEvent(ks);
      61           78 :     keysig->setShowCourtesy(showCourtesy);
      62              : 
      63              :     // Add/remove the corresponding key events, if appropriate.
      64           78 :     if (evtInStaff) {
      65           78 :         staff->setKey(tick, ks);     // replace
      66            0 :     } else if (curEvtInStaff) {
      67            0 :         staff->removeKey(tick);     // if nothing to add instead, just remove.
      68              :     }
      69              :     // If no keysig event corresponds to the key signature then this keysig
      70              :     // is probably generated. Otherwise it is probably added manually.
      71              :     // Set segment flags according to this, layout will change it if needed.
      72           78 :     segment->setEnabled(evtInStaff);
      73           78 :     segment->setHeader(!evtInStaff && segment->rtick() == Fraction(0, 1));
      74              : 
      75           78 :     showCourtesy = curShowCourtesy;
      76           78 :     ks           = curKey;
      77           78 :     evtInStaff   = curEvtInStaff;
      78           78 :     keysig->triggerLayout();
      79           78 :     keysig->score()->setLayout(keysig->staff()->nextKeyTick(tick), keysig->staffIdx());
      80           78 : }
      81              : 
      82              : //---------------------------------------------------------
      83              : //   EditKeySig
      84              : //---------------------------------------------------------
      85              : 
      86           29 : void EditKeySig::undoChangeKeySig(Transaction& tx, Score* score, Staff* ostaff, const Fraction& tick, KeySigEvent key)
      87              : {
      88           29 :     KeySig* lks = 0;
      89           29 :     bool needsUpdate = false;
      90              : 
      91           60 :     for (Staff* staff : ostaff->staffList()) {
      92           31 :         if (staff->isDrumStaff(tick)) {
      93            0 :             continue;
      94              :         }
      95              : 
      96           31 :         Score* staffScore = staff->score();
      97           31 :         Measure* measure = staffScore->tick2measure(tick);
      98           31 :         if (!measure) {
      99            0 :             LOGW("measure for tick %d not found!", tick.ticks());
     100            0 :             continue;
     101              :         }
     102           31 :         Segment* s   = measure->undoGetSegment(SegmentType::KeySig, tick);
     103              : 
     104           31 :         staff_idx_t staffIdx = staff->idx();
     105           31 :         track_idx_t track    = staffIdx * VOICES;
     106           31 :         KeySig* ks   = toKeySig(s->element(track));
     107              : 
     108           31 :         Interval interval = staff->part()->instrument(tick)->transpose();
     109           31 :         Interval oldStaffInterval = staff->transpose(tick);
     110           31 :         KeySigEvent nkey  = key;
     111           31 :         bool concertPitch = staffScore->style().styleB(Sid::concertPitch);
     112              : 
     113           31 :         if (interval.chromatic && !concertPitch && !nkey.isAtonal()) {
     114            4 :             interval.flip();
     115            4 :             nkey.setKey(Transpose::transposeKey(key.concertKey(), interval, staff->part()->preferSharpFlat()));
     116            4 :             interval.flip();
     117              :         }
     118              : 
     119           31 :         staffScore->updateInstrumentChangeTranspositions(key, staff, tick);
     120           31 :         if (ks) {
     121           16 :             ks->undoChangeProperty(Pid::GENERATED, false);
     122           16 :             tx.push(new ChangeKeySig(ks, nkey, ks->showCourtesy()));
     123              :         } else {
     124           15 :             KeySig* nks = Factory::createKeySig(s);
     125           15 :             nks->setTrack(track);
     126           15 :             nks->setKeySigEvent(nkey);
     127           15 :             staffScore->doUndoAddElement(nks);
     128           15 :             if (lks) {
     129            0 :                 tx.push(new Link(lks, nks));
     130              :             } else {
     131           15 :                 lks = nks;
     132              :             }
     133              :         }
     134           31 :         if (interval != staff->transpose(tick) || interval != oldStaffInterval) {
     135            1 :             needsUpdate = true;
     136              :         }
     137           60 :     }
     138           29 :     if (needsUpdate) {
     139            1 :         Fraction tickEnd = Fraction::fromTicks(ostaff->keyList()->nextKeyTick(tick.ticks()));
     140            1 :         Transpose::transpositionChanged(tx, score, ostaff->part(), ostaff->transpose(tick), tick, tickEnd);
     141              :     }
     142           29 : }
        

Generated by: LCOV version 2.0-1