LCOV - code coverage report
Current view: top level - src/preferences/qml/MuseScore/Preferences - preferencesmodel.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 161 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 <QGuiApplication>
      24              : 
      25              : #include "preferencesmodel.h"
      26              : 
      27              : #include "translation.h"
      28              : #include "ui/view/iconcodes.h"
      29              : 
      30              : #include "muse_framework_config.h"
      31              : 
      32              : using namespace mu::preferences;
      33              : using namespace muse::ui;
      34              : 
      35            0 : PreferencesModel::PreferencesModel(QObject* parent)
      36            0 :     : QAbstractItemModel(parent), muse::Contextable(muse::iocCtxForQmlObject(this))
      37              : {
      38            0 : }
      39              : 
      40            0 : PreferencesModel::~PreferencesModel()
      41              : {
      42            0 :     cancel();
      43              : 
      44            0 :     delete m_rootItem;
      45            0 :     m_rootItem = nullptr;
      46            0 : }
      47              : 
      48            0 : QModelIndex PreferencesModel::index(int row, int column, const QModelIndex& parent) const
      49              : {
      50            0 :     if (!hasIndex(row, column, parent)) {
      51            0 :         return QModelIndex();
      52              :     }
      53              : 
      54            0 :     PreferencePageItem* parentItem = nullptr;
      55              : 
      56            0 :     if (!parent.isValid()) {
      57            0 :         parentItem = m_rootItem;
      58              :     } else {
      59            0 :         parentItem = modelIndexToItem(parent);
      60              :     }
      61              : 
      62            0 :     if (!parentItem) {
      63            0 :         return QModelIndex();
      64              :     }
      65              : 
      66            0 :     PreferencePageItem* childItem = parentItem->childAtRow(row);
      67              : 
      68            0 :     if (childItem) {
      69            0 :         return createIndex(row, column, childItem);
      70              :     }
      71              : 
      72            0 :     return QModelIndex();
      73              : }
      74              : 
      75            0 : QModelIndex PreferencesModel::parent(const QModelIndex& child) const
      76              : {
      77            0 :     PreferencePageItem* childItem = modelIndexToItem(child);
      78            0 :     if (!childItem) {
      79            0 :         return QModelIndex();
      80              :     }
      81              : 
      82            0 :     PreferencePageItem* parentItem = qobject_cast<PreferencePageItem*>(childItem->parentItem());
      83              : 
      84            0 :     if (parentItem == m_rootItem) {
      85            0 :         return QModelIndex();
      86              :     }
      87              : 
      88            0 :     return createIndex(parentItem->row(), 0, parentItem);
      89              : }
      90              : 
      91            0 : int PreferencesModel::rowCount(const QModelIndex& parent) const
      92              : {
      93            0 :     PreferencePageItem* parentItem = nullptr;
      94              : 
      95            0 :     if (!parent.isValid()) {
      96            0 :         parentItem = m_rootItem;
      97              :     } else {
      98            0 :         parentItem = modelIndexToItem(parent);
      99              :     }
     100              : 
     101            0 :     if (!parentItem) {
     102            0 :         return 0;
     103              :     }
     104              : 
     105            0 :     return parentItem->childCount();
     106              : }
     107              : 
     108            0 : int PreferencesModel::columnCount(const QModelIndex&) const
     109              : {
     110            0 :     return 1;
     111              : }
     112              : 
     113            0 : QVariant PreferencesModel::data(const QModelIndex& index, int role) const
     114              : {
     115            0 :     if (!index.isValid() && role != ItemRole) {
     116            0 :         return QVariant();
     117              :     }
     118              : 
     119            0 :     PreferencePageItem* item = modelIndexToItem(index);
     120              : 
     121            0 :     if (!item) {
     122            0 :         return QVariant();
     123              :     }
     124              : 
     125            0 :     return QVariant::fromValue(qobject_cast<QObject*>(item));
     126              : }
     127              : 
     128            0 : QHash<int, QByteArray> PreferencesModel::roleNames() const
     129              : {
     130            0 :     return { { ItemRole, "item" } };
     131            0 : }
     132              : 
     133            0 : QString PreferencesModel::currentPageId() const
     134              : {
     135            0 :     return m_currentPageId;
     136              : }
     137              : 
     138            0 : void PreferencesModel::load(const QString& currentPageId)
     139              : {
     140            0 :     configuration()->startEditSettings();
     141              : 
     142            0 :     beginResetModel();
     143              : 
     144            0 :     if (!currentPageId.isEmpty()) {
     145            0 :         setCurrentPageId(currentPageId);
     146              :     } else {
     147            0 :         const QString& lastOpenedPageId = configuration()->preferencesDialogLastOpenedPageId();
     148            0 :         if (lastOpenedPageId.isEmpty()) {
     149            0 :             setCurrentPageId("general");
     150              :         } else {
     151            0 :             setCurrentPageId(lastOpenedPageId);
     152              :         }
     153              :     }
     154              : 
     155            0 :     m_rootItem = new PreferencePageItem();
     156              : 
     157              :     QList<PreferencePageItem*> items {
     158            0 :         makeItem("general", QT_TRANSLATE_NOOP("preferences", "General"), IconCode::Code::SETTINGS_COG,
     159              :                  "Preferences/GeneralPreferencesPage.qml"),
     160              : 
     161            0 :         makeItem("appearance", QT_TRANSLATE_NOOP("preferences", "Appearance"), IconCode::Code::EYE_OPEN,
     162              :                  "Preferences/AppearancePreferencesPage.qml"),
     163              : 
     164            0 :         makeItem("canvas", QT_TRANSLATE_NOOP("preferences", "Canvas"), IconCode::Code::NEW_FILE,
     165              :                  "Preferences/CanvasPreferencesPage.qml"),
     166              : 
     167            0 :         makeItem("cloud", QT_TRANSLATE_NOOP("preferences", "Save & publish"), IconCode::Code::CLOUD_FILE,
     168              :                  "Preferences/SaveAndPublishPreferencesPage.qml"),
     169              : 
     170            0 :         makeItem("note-input", QT_TRANSLATE_NOOP("preferences", "Note input"), IconCode::Code::EDIT,
     171              :                  "Preferences/NoteInputPreferencesPage.qml"),
     172              : 
     173            0 :         makeItem("score", QT_TRANSLATE_NOOP("preferences", "Score"), IconCode::Code::SCORE,
     174              :                  "Preferences/ScorePreferencesPage.qml"),
     175              : 
     176            0 :         makeItem("audio-midi", QT_TRANSLATE_NOOP("preferences", "Audio & MIDI"), IconCode::Code::AUDIO,
     177              :                  "Preferences/AudioMidiPreferencesPage.qml"),
     178              : 
     179              : #ifdef MUSE_MODULE_MIDIREMOTE
     180            0 :         makeItem("midi-device-mapping", QT_TRANSLATE_NOOP("preferences", "MIDI mappings"), IconCode::Code::MIDI_INPUT,
     181              :                  "Preferences/MidiDeviceMappingPreferencesPage.qml"),
     182              : #endif
     183              : 
     184            0 :         makeItem("video", QT_TRANSLATE_NOOP("preferences", "Video"), IconCode::Code::VIDEO,
     185              :                  "Preferences/VideoPreferencesPage.qml"),
     186              : 
     187            0 :         makeItem("percussion", QT_TRANSLATE_NOOP("preferences", "Percussion"), IconCode::Code::PERCUSSION,
     188              :                  "Preferences/PercussionPreferencesPage.qml"),
     189              : 
     190            0 :         makeItem("import", QT_TRANSLATE_NOOP("preferences", "Import"), IconCode::Code::IMPORT,
     191              :                  "Preferences/ImportPreferencesPage.qml"),
     192              : 
     193            0 :         makeItem("shortcuts", QT_TRANSLATE_NOOP("preferences", "Shortcuts"), IconCode::Code::SHORTCUTS,
     194              :                  "Preferences/ShortcutsPreferencesPage.qml"),
     195              : 
     196            0 :         makeItem("general-folders", QT_TRANSLATE_NOOP("preferences", "Folders"), IconCode::Code::OPEN_FILE,
     197              :                  "Preferences/FoldersPreferencesPage.qml"),
     198              : 
     199            0 :         makeItem("advanced", QT_TRANSLATE_NOOP("preferences", "Advanced"), IconCode::Code::CONFIGURE,
     200              :                  "Preferences/AdvancedPreferencesPage.qml"),
     201              : 
     202            0 :         makeItem("braille", QT_TRANSLATE_NOOP("preferences", "Braille"), IconCode::Code::BRAILLE,
     203              :                  "Preferences/BraillePreferencesPage.qml")
     204            0 :     };
     205              : 
     206            0 :     for (PreferencePageItem* item: items) {
     207            0 :         m_rootItem->appendChild(item);
     208              :     }
     209              : 
     210            0 :     endResetModel();
     211            0 : }
     212              : 
     213            0 : void PreferencesModel::askForConfirmationOfPreferencesReset()
     214              : {
     215            0 :     std::string title = muse::trc("appshell", "Are you sure you want to reset preferences?");
     216              :     std::string question = muse::trc("appshell", "This action will reset all your app preferences and delete all custom shortcuts. "
     217              :                                                  "It will not delete any of your scores.\n\n"
     218            0 :                                                  "This action cannot be undone.");
     219              : 
     220            0 :     muse::IInteractive::ButtonData cancelBtn = interactive()->buttonData(muse::IInteractive::Button::Cancel);
     221            0 :     muse::IInteractive::ButtonData resetBtn = interactive()->buttonData(muse::IInteractive::Button::Reset);
     222            0 :     cancelBtn.accent = true;
     223              : 
     224            0 :     interactive()->warning(title, question, { cancelBtn, resetBtn }, cancelBtn.btn,
     225              :                            { muse::IInteractive::Option::WithIcon },
     226            0 :                            muse::trc("appshell", "Reset preferences"))
     227            0 :     .onResolve(this, [this](const muse::IInteractive::Result& res) {
     228            0 :         if (res.isButton(muse::IInteractive::Button::Reset)) {
     229            0 :             emit userAgreesToResetPreferences();
     230              :         }
     231            0 :     });
     232            0 : }
     233              : 
     234            0 : void PreferencesModel::resetFactorySettings()
     235              : {
     236              :     static constexpr bool KEEP_DEFAULT_SETTINGS = true;
     237            0 :     QGuiApplication::setOverrideCursor(Qt::WaitCursor);
     238            0 :     QGuiApplication::processEvents();
     239            0 :     configuration()->revertToFactorySettings(KEEP_DEFAULT_SETTINGS);
     240              : 
     241              :     // Unreset the "First Launch Completed" setting so the first-time launch wizard does not appear.
     242            0 :     configuration()->setHasCompletedFirstLaunchSetup(true);
     243              : 
     244            0 :     configuration()->startEditSettings();
     245            0 :     QGuiApplication::restoreOverrideCursor();
     246            0 : }
     247              : 
     248            0 : void PreferencesModel::apply()
     249              : {
     250            0 :     configuration()->applySettings();
     251            0 : }
     252              : 
     253            0 : void PreferencesModel::cancel()
     254              : {
     255            0 :     configuration()->rollbackSettings();
     256            0 : }
     257              : 
     258            0 : void PreferencesModel::selectRow(const QModelIndex& rowIndex)
     259              : {
     260            0 :     QModelIndex parentItemIndex = parent(rowIndex);
     261            0 :     PreferencePageItem* parentItem = nullptr;
     262            0 :     if (!parentItemIndex.isValid()) {
     263            0 :         parentItem = m_rootItem;
     264              :     } else {
     265            0 :         parentItem = modelIndexToItem(parentItemIndex);
     266              :     }
     267              : 
     268            0 :     QList<PreferencePageItem*> children = parentItem->childrenItems();
     269            0 :     for (PreferencePageItem* child: children) {
     270            0 :         child->setExpanded(false);
     271              :     }
     272              : 
     273            0 :     PreferencePageItem* selectedItem = parentItem->childAtRow(rowIndex.row());
     274            0 :     if (!selectedItem) {
     275            0 :         return;
     276              :     }
     277              : 
     278            0 :     selectedItem->setExpanded(true);
     279            0 :     setCurrentPageId(selectedItem->id());
     280            0 : }
     281              : 
     282            0 : QVariantList PreferencesModel::availablePages() const
     283              : {
     284            0 :     std::function<QVariantList(const PreferencePageItem*)> childPages;
     285            0 :     childPages = [&childPages](const PreferencePageItem* item) {
     286            0 :         QVariantList result;
     287              : 
     288            0 :         for (int i = 0; i < item->childCount(); ++i) {
     289            0 :             PreferencePageItem* child = item->childAtRow(i);
     290            0 :             QVariantMap childObj;
     291            0 :             childObj["id"] = child->id();
     292            0 :             childObj["path"] = child->path();
     293            0 :             result << childObj;
     294              : 
     295            0 :             QVariantList pages = childPages(child);
     296            0 :             for (const QVariant& page: pages) {
     297            0 :                 result << page;
     298              :             }
     299            0 :         }
     300              : 
     301            0 :         return result;
     302            0 :     };
     303              : 
     304            0 :     return childPages(m_rootItem);
     305            0 : }
     306              : 
     307            0 : void PreferencesModel::setCurrentPageId(QString currentPageId)
     308              : {
     309            0 :     if (m_currentPageId == currentPageId) {
     310            0 :         return;
     311              :     }
     312              : 
     313            0 :     m_currentPageId = currentPageId;
     314            0 :     configuration()->setPreferencesDialogLastOpenedPageId(currentPageId);
     315            0 :     emit currentPageIdChanged(m_currentPageId);
     316              : }
     317              : 
     318            0 : PreferencePageItem* PreferencesModel::makeItem(const QString& id, const QString& title, muse::ui::IconCode::Code icon,
     319              :                                                const QString& path,
     320              :                                                const QList<PreferencePageItem*>& children) const
     321              : {
     322            0 :     PreferencePageItem* item = new PreferencePageItem();
     323            0 :     item->setId(id);
     324            0 :     item->setTitle(title);
     325            0 :     item->setIcon(icon);
     326            0 :     item->setPath(path);
     327            0 :     item->setExpanded(id == currentPageId());
     328              : 
     329            0 :     for (PreferencePageItem* child: children) {
     330            0 :         item->appendChild(child);
     331              : 
     332            0 :         if (child->id() == currentPageId()) {
     333            0 :             item->setExpanded(true);
     334              :         }
     335              :     }
     336              : 
     337            0 :     return item;
     338              : }
     339              : 
     340            0 : PreferencePageItem* PreferencesModel::modelIndexToItem(const QModelIndex& index) const
     341              : {
     342            0 :     return static_cast<PreferencePageItem*>(index.internalPointer());
     343              : }
        

Generated by: LCOV version 2.0-1