LCOV - code coverage report
Current view: top level - src/notationscene/widgets - transposedialog.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 158 0
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              : 
      23              : #include "transposedialog.h"
      24              : 
      25              : #include "notation/inotation.h"
      26              : #include "notation/inotationinteraction.h"
      27              : #include "notation/inotationselection.h"
      28              : 
      29              : #include "ui/view/widgetstatestore.h"
      30              : 
      31              : using namespace mu::notation;
      32              : using namespace muse::ui;
      33              : 
      34              : //---------------------------------------------------------
      35              : //   TransposeDialog
      36              : //---------------------------------------------------------
      37              : 
      38            0 : TransposeDialog::TransposeDialog(QWidget* parent)
      39            0 :     : muse::ui::WidgetDialog(parent)
      40              : {
      41            0 :     setObjectName("TransposeDialog");
      42            0 :     setupUi(this);
      43            0 :     setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
      44              : 
      45            0 :     connect(transposeByKey,      &QGroupBox::clicked, this, &TransposeDialog::transposeByKeyToggled);
      46            0 :     connect(transposeByInterval, &QGroupBox::clicked, this, &TransposeDialog::transposeByIntervalToggled);
      47            0 :     connect(chromaticBox,        &QGroupBox::clicked, this, &TransposeDialog::chromaticBoxToggled);
      48            0 :     connect(diatonicBox,         &QGroupBox::clicked, this, &TransposeDialog::diatonicBoxToggled);
      49            0 : }
      50              : 
      51            0 : void TransposeDialog::componentComplete()
      52              : {
      53            0 :     if (selection()->isNone()) {
      54            0 :         interaction()->select(SelectionTarget::All);
      55            0 :         m_allSelected = true;
      56              :     }
      57              : 
      58              :     // TRANSPOSE_TO_KEY and "transpose keys" is only possible if selection state is SelState::RANGE
      59            0 :     bool rangeSelection = selection()->isRange();
      60            0 :     setEnableTransposeKeys(rangeSelection);
      61            0 :     setEnableTransposeToKey(rangeSelection);
      62              : 
      63            0 :     const std::vector<EngravingItem*>& elements = selection()->elements();
      64            0 :     bool hasChordNames = std::any_of(elements.cbegin(), elements.cend(), [](const EngravingItem* item) {
      65            0 :         return item->isHarmony() || item->isFretDiagram();
      66              :     });
      67            0 :     setEnableTransposeChordNames(hasChordNames);
      68              : 
      69            0 :     restorePreviousState();
      70              : 
      71            0 :     connect(this, &TransposeDialog::accepted, this, &TransposeDialog::apply);
      72              : 
      73              :     //! NOTE: It is necessary for the correct start of navigation in the dialog
      74            0 :     setFocus();
      75            0 : }
      76              : 
      77              : //---------------------------------------------------------
      78              : //   TransposeDialog slots
      79              : //---------------------------------------------------------
      80              : 
      81            0 : void TransposeDialog::transposeByKeyToggled(bool val)
      82              : {
      83            0 :     if (val) {
      84            0 :         transposeByInterval->setChecked(false);
      85              :     } else {
      86            0 :         if (!transposeByInterval->isChecked()) {
      87            0 :             transposeByKey->setChecked(true);
      88              :         }
      89              :     }
      90            0 : }
      91              : 
      92            0 : void TransposeDialog::transposeByIntervalToggled(bool val)
      93              : {
      94            0 :     if (val) {
      95            0 :         transposeByKey->setChecked(false);
      96              :     } else {
      97            0 :         if (!transposeByKey->isChecked()) {
      98            0 :             transposeByInterval->setChecked(true);
      99              :         }
     100              :     }
     101            0 : }
     102              : 
     103            0 : void TransposeDialog::chromaticBoxToggled(bool val)
     104              : {
     105            0 :     if (val) {
     106            0 :         diatonicBox->setChecked(false);
     107              :     } else {
     108            0 :         if (!diatonicBox->isChecked()) {
     109            0 :             chromaticBox->setChecked(true);
     110              :         }
     111              :     }
     112            0 : }
     113              : 
     114            0 : void TransposeDialog::diatonicBoxToggled(bool val)
     115              : {
     116            0 :     if (val) {
     117            0 :         chromaticBox->setChecked(false);
     118              :     } else {
     119            0 :         if (!chromaticBox->isChecked()) {
     120            0 :             diatonicBox->setChecked(true);
     121              :         }
     122              :     }
     123            0 : }
     124              : 
     125              : //---------------------------------------------------------
     126              : //   mode
     127              : //---------------------------------------------------------
     128              : 
     129            0 : TransposeMode TransposeDialog::mode() const
     130              : {
     131            0 :     return chromaticBox->isChecked()
     132            0 :            ? (transposeByKey->isChecked() ? TransposeMode::TO_KEY : TransposeMode::BY_INTERVAL)
     133            0 :            : TransposeMode::DIATONICALLY;
     134              : }
     135              : 
     136              : //---------------------------------------------------------
     137              : //   enableTransposeByKey
     138              : //---------------------------------------------------------
     139              : 
     140            0 : void TransposeDialog::setEnableTransposeToKey(bool val)
     141              : {
     142            0 :     transposeByKey->setEnabled(val);
     143            0 :     transposeByInterval->setChecked(!val);
     144            0 :     transposeByKey->setChecked(val);
     145            0 : }
     146              : 
     147              : //---------------------------------------------------------
     148              : //   enableTransposeChordNames
     149              : //---------------------------------------------------------
     150              : 
     151            0 : void TransposeDialog::setEnableTransposeChordNames(bool val)
     152              : {
     153            0 :     transposeChordNames->setEnabled(val);
     154            0 : }
     155              : 
     156              : //---------------------------------------------------------
     157              : //   direction
     158              : //---------------------------------------------------------
     159              : 
     160            0 : TransposeDirection TransposeDialog::direction() const
     161              : {
     162            0 :     switch (mode()) {
     163            0 :     case TransposeMode::TO_KEY:
     164            0 :         if (closestKey->isChecked()) {
     165            0 :             return TransposeDirection::CLOSEST;
     166              :         }
     167            0 :         return upKey->isChecked() ? TransposeDirection::UP : TransposeDirection::DOWN;
     168            0 :     case TransposeMode::BY_INTERVAL:
     169            0 :         return upInterval->isChecked() ? TransposeDirection::UP : TransposeDirection::DOWN;
     170            0 :     case TransposeMode::DIATONICALLY:
     171            0 :         return upDiatonic->isChecked() ? TransposeDirection::UP : TransposeDirection::DOWN;
     172            0 :     case TransposeMode::UNKNOWN:
     173            0 :         return TransposeDirection::UNKNOWN;
     174              :     }
     175            0 :     return TransposeDirection::UP;
     176              : }
     177              : 
     178              : //---------------------------------------------------------
     179              : //   showEvent
     180              : //---------------------------------------------------------
     181              : 
     182            0 : void TransposeDialog::showEvent(QShowEvent* event)
     183              : {
     184            0 :     WidgetStateStore::restoreGeometry(this);
     185            0 :     QDialog::showEvent(event);
     186            0 : }
     187              : 
     188              : //---------------------------------------------------------
     189              : //   hideEvent
     190              : //---------------------------------------------------------
     191              : 
     192            0 : void TransposeDialog::hideEvent(QHideEvent* event)
     193              : {
     194            0 :     WidgetStateStore::saveGeometry(this);
     195            0 :     QWidget::hideEvent(event);
     196            0 : }
     197              : 
     198            0 : INotationPtr TransposeDialog::notation() const
     199              : {
     200            0 :     return context()->currentNotation();
     201              : }
     202              : 
     203            0 : INotationInteractionPtr TransposeDialog::interaction() const
     204              : {
     205            0 :     return notation()->interaction();
     206              : }
     207              : 
     208            0 : INotationSelectionPtr TransposeDialog::selection() const
     209              : {
     210            0 :     return interaction()->selection();
     211              : }
     212              : 
     213            0 : void TransposeDialog::apply()
     214              : {
     215            0 :     TransposeOptions options;
     216            0 :     options.mode = mode();
     217            0 :     options.direction = direction();
     218            0 :     options.key = transposeKey();
     219            0 :     options.interval = transposeInterval();
     220            0 :     options.needTransposeKeys = getTransposeKeys();
     221            0 :     options.needTransposeChordNames = getTransposeChordNames();
     222            0 :     options.needTransposeDoubleSharpsFlats = useDoubleSharpsFlats();
     223              : 
     224            0 :     saveState();
     225              : 
     226            0 :     interaction()->transpose(options);
     227              : 
     228            0 :     if (m_allSelected) {
     229            0 :         interaction()->clearSelection();
     230              :     }
     231            0 : }
     232              : 
     233            0 : void TransposeDialog::setEnableTransposeKeys(bool val)
     234              : {
     235            0 :     transposeKeys->setEnabled(val);
     236            0 : }
     237              : 
     238            0 : bool TransposeDialog::getTransposeKeys() const
     239              : {
     240            0 :     return chromaticBox->isChecked()
     241            0 :            ? transposeKeys->isChecked()
     242            0 :            : keepDegreeAlterations->isChecked();
     243              : }
     244              : 
     245            0 : bool TransposeDialog::getTransposeChordNames() const
     246              : {
     247            0 :     return transposeChordNames->isChecked();
     248              : }
     249              : 
     250            0 : Key TransposeDialog::transposeKey() const
     251              : {
     252            0 :     return Key(keyList->currentIndex() - 7);
     253              : }
     254              : 
     255            0 : int TransposeDialog::transposeInterval() const
     256              : {
     257            0 :     return chromaticBox->isChecked()
     258            0 :            ? intervalList->currentIndex()
     259            0 :            : degreeList->currentIndex() + 1;
     260              : }
     261              : 
     262            0 : bool TransposeDialog::useDoubleSharpsFlats() const
     263              : {
     264            0 :     return accidentalOptions->currentIndex() == 1;
     265              : }
     266              : 
     267            0 : TransposeDialogState& TransposeDialog::previousState()
     268              : {
     269              :     static TransposeDialogState options;
     270            0 :     return options;
     271              : }
     272              : 
     273            0 : void TransposeDialog::restorePreviousState()
     274              : {
     275            0 :     const TransposeDialogState& state = previousState();
     276              : 
     277            0 :     chromaticBox->setChecked(state.chromaticChecked);
     278            0 :     diatonicBox->setChecked(!state.chromaticChecked);
     279              : 
     280            0 :     transposeByKey->setChecked(state.transposeByKeyChecked);
     281            0 :     transposeByInterval->setChecked(!state.transposeByKeyChecked);
     282              : 
     283            0 :     keyList->setCurrentIndex(state.keyListIdx);
     284            0 :     closestKey->setChecked(state.closestKeyChecked);
     285            0 :     upKey->setChecked(state.upKeyChecked);
     286            0 :     downKey->setChecked(!state.closestKeyChecked && !state.upKeyChecked);
     287              : 
     288            0 :     intervalList->setCurrentIndex(state.chromaticIntervalIdx);
     289            0 :     upInterval->setChecked(state.upIntervalChecked);
     290            0 :     downInterval->setChecked(!state.upIntervalChecked);
     291              : 
     292            0 :     transposeKeys->setChecked(state.needTransposeKeysChecked);
     293              : 
     294            0 :     degreeList->setCurrentIndex(state.diatonicIntervalIdx);
     295            0 :     upDiatonic->setChecked(state.upDiatonicChecked);
     296            0 :     downDiatonic->setChecked(!state.upDiatonicChecked);
     297            0 :     keepDegreeAlterations->setChecked(state.keepDegreeAlterationsChecked);
     298              : 
     299            0 :     transposeChordNames->setChecked(state.needTransposeChordNamesChecked);
     300            0 :     accidentalOptions->setCurrentIndex(state.needTransposeDoubleSharpsFlatsIdx);
     301            0 : }
     302              : 
     303            0 : void TransposeDialog::saveState()
     304              : {
     305            0 :     TransposeDialogState& state = previousState();
     306              : 
     307            0 :     state.chromaticChecked = chromaticBox->isChecked();
     308            0 :     state.transposeByKeyChecked = transposeByKey->isChecked();
     309            0 :     state.closestKeyChecked = closestKey->isChecked();
     310            0 :     state.upKeyChecked = upKey->isChecked();
     311            0 :     state.keyListIdx = keyList->currentIndex();
     312            0 :     state.upIntervalChecked = upInterval->isChecked();
     313            0 :     state.chromaticIntervalIdx = intervalList->currentIndex();
     314            0 :     state.upDiatonicChecked = upDiatonic->isChecked();
     315            0 :     state.diatonicIntervalIdx = degreeList->currentIndex();
     316            0 :     state.keepDegreeAlterationsChecked = keepDegreeAlterations->isChecked();
     317            0 :     state.needTransposeKeysChecked = transposeKeys->isChecked();
     318            0 :     state.needTransposeChordNamesChecked = transposeChordNames->isChecked();
     319            0 :     state.needTransposeDoubleSharpsFlatsIdx = accidentalOptions->currentIndex();
     320            0 : }
        

Generated by: LCOV version 2.0-1