diff --git a/src/appshell/iappshellconfiguration.h b/src/appshell/iappshellconfiguration.h index b7d6c1965f113..2e1eb7dd13145 100644 --- a/src/appshell/iappshellconfiguration.h +++ b/src/appshell/iappshellconfiguration.h @@ -23,7 +23,7 @@ #define MU_APPSHELL_IAPPSHELLCONFIGURATION_H #include "modularity/imoduleinterface.h" -#include "types/retval.h" +#include "types/ret.h" #include "io/path.h" #include "appshelltypes.h" @@ -42,9 +42,11 @@ class IAppShellConfiguration : MODULE_EXPORT_INTERFACE virtual StartupModeType startupModeType() const = 0; virtual void setStartupModeType(StartupModeType type) = 0; + virtual muse::async::Notification startupModeTypeChanged() const = 0; virtual muse::io::path_t startupScorePath() const = 0; virtual void setStartupScorePath(const muse::io::path_t& scorePath) = 0; + virtual muse::async::Notification startupScorePathChanged() const = 0; virtual muse::io::path_t userDataPath() const = 0; @@ -73,7 +75,7 @@ class IAppShellConfiguration : MODULE_EXPORT_INTERFACE virtual void applySettings() = 0; virtual void rollbackSettings() = 0; - virtual void revertToFactorySettings(bool keepDefaultSettings = false, bool notifyAboutChanges = true) const = 0; + virtual void revertToFactorySettings(bool keepDefaultSettings = false, bool notifyAboutChanges = true) = 0; virtual muse::io::paths_t sessionProjectsPaths() const = 0; virtual muse::Ret setSessionProjectsPaths(const muse::io::paths_t& paths) = 0; diff --git a/src/appshell/internal/applicationactioncontroller.cpp b/src/appshell/internal/applicationactioncontroller.cpp index 77cd547ce0af9..f983f6e12c6e6 100644 --- a/src/appshell/internal/applicationactioncontroller.cpp +++ b/src/appshell/internal/applicationactioncontroller.cpp @@ -326,11 +326,15 @@ void ApplicationActionController::revertToFactorySettings() "The list of recent scores will also be cleared.\n\n" "This action will not delete any of your scores."); + IInteractive::ButtonData cancelBtn = interactive()->buttonData(IInteractive::Button::Cancel); + cancelBtn.accent = true; + int revertBtn = int(IInteractive::Button::Apply); IInteractive::Result result = interactive()->warning(title, question, - { interactive()->buttonData(IInteractive::Button::Cancel), - IInteractive::ButtonData(revertBtn, muse::trc("appshell", "Revert"), true) }, - revertBtn); + { cancelBtn, + IInteractive::ButtonData(revertBtn, muse::trc("appshell", "Revert")) }, + cancelBtn.btn, { muse::IInteractive::Option::WithIcon }, + muse::trc("appshell", "Revert to factory settings")); if (result.standardButton() == IInteractive::Button::Cancel) { return; diff --git a/src/appshell/internal/appshellconfiguration.cpp b/src/appshell/internal/appshellconfiguration.cpp index 68099a3366308..1fd1709f3a8d5 100644 --- a/src/appshell/internal/appshellconfiguration.cpp +++ b/src/appshell/internal/appshellconfiguration.cpp @@ -63,7 +63,14 @@ void AppShellConfiguration::init() settings()->setDefaultValue(HAS_COMPLETED_FIRST_LAUNCH_SETUP, Val(false)); settings()->setDefaultValue(STARTUP_MODE_TYPE, Val(StartupModeType::StartEmpty)); + settings()->valueChanged(STARTUP_MODE_TYPE).onReceive(this, [this](const Val&) { + m_startupModeTypeChanged.notify(); + }); + settings()->setDefaultValue(STARTUP_SCORE_PATH, Val(projectConfiguration()->myFirstProjectPath().toStdString())); + settings()->valueChanged(STARTUP_SCORE_PATH).onReceive(this, [this](const Val&) { + m_startupScorePathChanged.notify(); + }); fileSystem()->makePath(sessionDataPath()); } @@ -88,6 +95,11 @@ void AppShellConfiguration::setStartupModeType(StartupModeType type) settings()->setSharedValue(STARTUP_MODE_TYPE, Val(type)); } +async::Notification AppShellConfiguration::startupModeTypeChanged() const +{ + return m_startupModeTypeChanged; +} + muse::io::path_t AppShellConfiguration::startupScorePath() const { return settings()->value(STARTUP_SCORE_PATH).toString(); @@ -98,6 +110,11 @@ void AppShellConfiguration::setStartupScorePath(const muse::io::path_t& scorePat settings()->setSharedValue(STARTUP_SCORE_PATH, Val(scorePath.toStdString())); } +async::Notification AppShellConfiguration::startupScorePathChanged() const +{ + return m_startupScorePathChanged; +} + muse::io::path_t AppShellConfiguration::userDataPath() const { return globalConfiguration()->userDataPath(); @@ -213,7 +230,7 @@ void AppShellConfiguration::rollbackSettings() settings()->rollbackTransaction(); } -void AppShellConfiguration::revertToFactorySettings(bool keepDefaultSettings, bool notifyAboutChanges) const +void AppShellConfiguration::revertToFactorySettings(bool keepDefaultSettings, bool notifyAboutChanges) { settings()->reset(keepDefaultSettings, notifyAboutChanges); } diff --git a/src/appshell/internal/appshellconfiguration.h b/src/appshell/internal/appshellconfiguration.h index e21a79c44138e..b955f5ef48b39 100644 --- a/src/appshell/internal/appshellconfiguration.h +++ b/src/appshell/internal/appshellconfiguration.h @@ -61,9 +61,11 @@ class AppShellConfiguration : public IAppShellConfiguration, public muse::Inject StartupModeType startupModeType() const override; void setStartupModeType(StartupModeType type) override; + muse::async::Notification startupModeTypeChanged() const override; muse::io::path_t startupScorePath() const override; void setStartupScorePath(const muse::io::path_t& scorePath) override; + muse::async::Notification startupScorePathChanged() const override; muse::io::path_t userDataPath() const override; @@ -92,7 +94,7 @@ class AppShellConfiguration : public IAppShellConfiguration, public muse::Inject void applySettings() override; void rollbackSettings() override; - void revertToFactorySettings(bool keepDefaultSettings = false, bool notifyAboutChanges = true) const override; + void revertToFactorySettings(bool keepDefaultSettings = false, bool notifyAboutChanges = true) override; muse::io::paths_t sessionProjectsPaths() const override; muse::Ret setSessionProjectsPaths(const muse::io::paths_t& paths) override; @@ -111,6 +113,9 @@ class AppShellConfiguration : public IAppShellConfiguration, public muse::Inject muse::io::paths_t parseSessionProjectsPaths(const QByteArray& json) const; QString m_preferencesDialogCurrentPageId; + + muse::async::Notification m_startupModeTypeChanged; + muse::async::Notification m_startupScorePathChanged; }; } diff --git a/src/appshell/qml/Preferences/BraillePreferencesPage.qml b/src/appshell/qml/Preferences/BraillePreferencesPage.qml index 575eae2124e6b..503549f054942 100644 --- a/src/appshell/qml/Preferences/BraillePreferencesPage.qml +++ b/src/appshell/qml/Preferences/BraillePreferencesPage.qml @@ -34,6 +34,10 @@ PreferencesPage { id: preferencesModel } + Component.onCompleted: { + preferencesModel.load() + } + Column { width: parent.width spacing: root.sectionsSpacing diff --git a/src/appshell/qml/Preferences/ImportPreferencesPage.qml b/src/appshell/qml/Preferences/ImportPreferencesPage.qml index 1357912d9e156..3fd17c82cafe7 100644 --- a/src/appshell/qml/Preferences/ImportPreferencesPage.qml +++ b/src/appshell/qml/Preferences/ImportPreferencesPage.qml @@ -42,6 +42,7 @@ PreferencesPage { spacing: root.sectionsSpacing ImportStyleSection { + id: importStyleSection styleFileImportPath: importPreferencesModel.styleFileImportPath fileChooseTitle: importPreferencesModel.styleChooseTitle() filePathFilter: importPreferencesModel.stylePathFilter() @@ -145,4 +146,8 @@ PreferencesPage { } } } + + function reset() { + importStyleSection.reset() + } } diff --git a/src/appshell/qml/Preferences/PreferencesDialog.qml b/src/appshell/qml/Preferences/PreferencesDialog.qml index 1315ca75e4b11..8a6774d9f1058 100644 --- a/src/appshell/qml/Preferences/PreferencesDialog.qml +++ b/src/appshell/qml/Preferences/PreferencesDialog.qml @@ -149,6 +149,10 @@ StyledDialogView { navigation.order: 100000 onRevertFactorySettingsRequested: { + if (!preferencesModel.askForConfirmationOfPreferencesReset()) { + return; + } + var pages = preferencesModel.availablePages() for (var i in pages) { diff --git a/src/appshell/qml/Preferences/UpdatePreferencesPage.qml b/src/appshell/qml/Preferences/UpdatePreferencesPage.qml index db27e2eda6472..cd90ca569cc1e 100644 --- a/src/appshell/qml/Preferences/UpdatePreferencesPage.qml +++ b/src/appshell/qml/Preferences/UpdatePreferencesPage.qml @@ -34,6 +34,10 @@ PreferencesPage { id: updateModel } + Component.onCompleted: { + updateModel.load() + } + Column { width: parent.width spacing: root.sectionsSpacing diff --git a/src/appshell/qml/Preferences/internal/ImportStyleSection.qml b/src/appshell/qml/Preferences/internal/ImportStyleSection.qml index 63cdcd54a116b..3989ed37670ee 100644 --- a/src/appshell/qml/Preferences/internal/ImportStyleSection.qml +++ b/src/appshell/qml/Preferences/internal/ImportStyleSection.qml @@ -41,7 +41,12 @@ BaseSection { QtObject { id: prv - property bool useStyleFile: root.styleFileImportPath !== "" + property bool useStyleFileExplicitlySet: root.styleFileImportPath !== "" + property bool useStyleFile: prv.useStyleFileExplicitlySet || root.styleFileImportPath !== "" + } + + function reset() { + prv.useStyleFileExplicitlySet = false } RoundedRadioButton { @@ -57,7 +62,7 @@ BaseSection { navigation.column: 0 onToggled: { - prv.useStyleFile = false + prv.useStyleFileExplicitlySet = false root.styleFileImportPathChangeRequested("") } } @@ -81,7 +86,7 @@ BaseSection { navigation.column: 0 onToggled: { - prv.useStyleFile = true + prv.useStyleFileExplicitlySet = true } } diff --git a/src/appshell/view/preferences/advancedpreferencesmodel.cpp b/src/appshell/view/preferences/advancedpreferencesmodel.cpp index 6496a07b98cd6..2100d8ccd42f2 100644 --- a/src/appshell/view/preferences/advancedpreferencesmodel.cpp +++ b/src/appshell/view/preferences/advancedpreferencesmodel.cpp @@ -58,7 +58,7 @@ bool AdvancedPreferencesModel::setData(const QModelIndex& index, const QVariant& switch (role) { case ValueRole: - changeVal(index.row(), value); + changeVal(index.row(), Val::fromQVariant(value)); emit dataChanged(index, index, { ValueRole }); return true; default: @@ -96,20 +96,48 @@ void AdvancedPreferencesModel::load() for (auto it = items.cbegin(); it != items.cend(); ++it) { if (it->second.canBeManuallyEdited) { m_items << it->second; + + muse::Settings::Key key = it->second.key; + settings()->valueChanged(key).onReceive(this, [this, key](const Val& val) { + QModelIndex index = findIndex(key); + if (!index.isValid() || m_items[index.row()].value == val) { + return; + } + + changeModelVal(m_items[index.row()], val); + emit dataChanged(index, index, { ValueRole }); + }); } } endResetModel(); } -void AdvancedPreferencesModel::changeVal(int index, QVariant newVal) +QModelIndex AdvancedPreferencesModel::findIndex(const muse::Settings::Key& key) +{ + for (int i = 0; i < m_items.size(); ++i) { + if (m_items[i].key == key) { + return index(i, 0); + } + } + return QModelIndex(); +} + +void AdvancedPreferencesModel::changeVal(int index, const Val& newVal) { Settings::Item& item = m_items[index]; + changeModelVal(item, newVal); + settings()->setSharedValue(item.key, item.value); +} + +void AdvancedPreferencesModel::changeModelVal(Settings::Item& item, const Val& newVal) +{ + if (item.value == newVal) { + return; + } Val::Type type = item.value.type(); - item.value = Val::fromQVariant(newVal); + item.value = newVal; item.value.setType(type); - - settings()->setSharedValue(item.key, item.value); } void AdvancedPreferencesModel::resetToDefault() @@ -117,7 +145,7 @@ void AdvancedPreferencesModel::resetToDefault() beginResetModel(); for (int i = 0; i < m_items.size(); ++i) { - changeVal(i, m_items[i].defaultValue.toQVariant()); + changeVal(i, m_items[i].defaultValue); } endResetModel(); diff --git a/src/appshell/view/preferences/advancedpreferencesmodel.h b/src/appshell/view/preferences/advancedpreferencesmodel.h index 252f545cab552..f6fa00e0b6aec 100644 --- a/src/appshell/view/preferences/advancedpreferencesmodel.h +++ b/src/appshell/view/preferences/advancedpreferencesmodel.h @@ -24,10 +24,11 @@ #include +#include "async/asyncable.h" #include "settings.h" namespace mu::appshell { -class AdvancedPreferencesModel : public QAbstractListModel +class AdvancedPreferencesModel : public QAbstractListModel, public muse::async::Asyncable { Q_OBJECT @@ -53,7 +54,9 @@ class AdvancedPreferencesModel : public QAbstractListModel MaxValueRole }; - void changeVal(int index, QVariant newVal); + QModelIndex findIndex(const muse::Settings::Key& key); + void changeVal(int index, const muse::Val& newVal); + void changeModelVal(muse::Settings::Item& item, const muse::Val& newVal); QString typeToString(muse::Val::Type type) const; QList m_items; diff --git a/src/appshell/view/preferences/audiomidipreferencesmodel.cpp b/src/appshell/view/preferences/audiomidipreferencesmodel.cpp index e159964a330cb..9be02db3429c6 100644 --- a/src/appshell/view/preferences/audiomidipreferencesmodel.cpp +++ b/src/appshell/view/preferences/audiomidipreferencesmodel.cpp @@ -92,6 +92,10 @@ void AudioMidiPreferencesModel::init() emit midiOutputDeviceIdChanged(); }); + midiConfiguration()->useMIDI20OutputChanged().onReceive(this, [this](bool) { + emit useMIDI20OutputChanged(); + }); + playbackConfiguration()->muteHiddenInstrumentsChanged().onReceive(this, [this](bool mute) { emit muteHiddenInstrumentsChanged(mute); }); diff --git a/src/appshell/view/preferences/braillepreferencesmodel.cpp b/src/appshell/view/preferences/braillepreferencesmodel.cpp index e3d675b0aa0d9..beb97263d3d57 100644 --- a/src/appshell/view/preferences/braillepreferencesmodel.cpp +++ b/src/appshell/view/preferences/braillepreferencesmodel.cpp @@ -32,6 +32,21 @@ BraillePreferencesModel::BraillePreferencesModel(QObject* parent) { } +void BraillePreferencesModel::load() +{ + brailleConfiguration()->braillePanelEnabledChanged().onNotify(this, [this]() { + emit braillePanelEnabledChanged(braillePanelEnabled()); + }); + + brailleConfiguration()->intervalDirectionChanged().onNotify(this, [this]() { + emit intervalDirectionChanged(intervalDirection()); + }); + + brailleConfiguration()->brailleTableChanged().onNotify(this, [this]() { + emit brailleTableChanged(brailleTable()); + }); +} + bool BraillePreferencesModel::braillePanelEnabled() const { return brailleConfiguration()->braillePanelEnabled(); diff --git a/src/appshell/view/preferences/braillepreferencesmodel.h b/src/appshell/view/preferences/braillepreferencesmodel.h index 6859727494a07..8c3fad0f98045 100644 --- a/src/appshell/view/preferences/braillepreferencesmodel.h +++ b/src/appshell/view/preferences/braillepreferencesmodel.h @@ -25,11 +25,12 @@ #include +#include "async/asyncable.h" #include "modularity/ioc.h" #include "braille/ibrailleconfiguration.h" namespace mu::appshell { -class BraillePreferencesModel : public QObject, public muse::Injectable +class BraillePreferencesModel : public QObject, public muse::Injectable, public muse::async::Asyncable { Q_OBJECT @@ -42,6 +43,8 @@ class BraillePreferencesModel : public QObject, public muse::Injectable public: explicit BraillePreferencesModel(QObject* parent = nullptr); + Q_INVOKABLE void load(); + bool braillePanelEnabled() const; QString brailleTable() const; int intervalDirection() const; diff --git a/src/appshell/view/preferences/canvaspreferencesmodel.cpp b/src/appshell/view/preferences/canvaspreferencesmodel.cpp index 1c284e165a64e..4c3dc26de3c3b 100644 --- a/src/appshell/view/preferences/canvaspreferencesmodel.cpp +++ b/src/appshell/view/preferences/canvaspreferencesmodel.cpp @@ -37,6 +37,25 @@ void CanvasPreferencesModel::load() setupConnections(); } +void CanvasPreferencesModel::setupConnections() +{ + notationConfiguration()->defaultZoomChanged().onNotify(this, [this]() { + emit defaultZoomChanged(); + }); + notationConfiguration()->mouseZoomPrecisionChanged().onNotify(this, [this]() { + emit mouseZoomPrecisionChanged(); + }); + notationConfiguration()->canvasOrientation().ch.onReceive(this, [this](muse::Orientation) { + emit scrollPagesOrientationChanged(); + }); + notationConfiguration()->isLimitCanvasScrollAreaChanged().onNotify(this, [this]() { + emit limitScrollAreaChanged(); + }); + notationConfiguration()->selectionProximityChanged().onReceive(this, [this](int selectionProximity) { + emit selectionProximityChanged(selectionProximity); + }); +} + QVariantList CanvasPreferencesModel::zoomTypes() const { QVariantList types = { @@ -140,13 +159,6 @@ void CanvasPreferencesModel::setSelectionProximity(int proximity) emit selectionProximityChanged(proximity); } -void CanvasPreferencesModel::setupConnections() -{ - notationConfiguration()->canvasOrientation().ch.onReceive(this, [this](muse::Orientation) { - emit scrollPagesOrientationChanged(); - }); -} - ZoomType CanvasPreferencesModel::defaultZoomType() const { return notationConfiguration()->defaultZoomType(); diff --git a/src/appshell/view/preferences/generalpreferencesmodel.cpp b/src/appshell/view/preferences/generalpreferencesmodel.cpp index b14b6687202df..49fce019364ab 100644 --- a/src/appshell/view/preferences/generalpreferencesmodel.cpp +++ b/src/appshell/view/preferences/generalpreferencesmodel.cpp @@ -45,6 +45,14 @@ void GeneralPreferencesModel::load() languagesService()->needRestartToApplyLanguageChangeChanged().onReceive(this, [this](bool need) { setIsNeedRestart(need); }); + + configuration()->startupModeTypeChanged().onNotify(this, [this]() { + emit startupModesChanged(); + }); + + configuration()->startupScorePathChanged().onNotify(this, [this]() { + emit startupModesChanged(); + }); } void GeneralPreferencesModel::checkUpdateForCurrentLanguage() @@ -244,6 +252,5 @@ void GeneralPreferencesModel::setStartupScorePath(const QString& scorePath) } configuration()->setStartupScorePath(scorePath); - emit startupModesChanged(); } diff --git a/src/appshell/view/preferences/importpreferencesmodel.cpp b/src/appshell/view/preferences/importpreferencesmodel.cpp index a1c323e3c35d5..fe0b78710883e 100644 --- a/src/appshell/view/preferences/importpreferencesmodel.cpp +++ b/src/appshell/view/preferences/importpreferencesmodel.cpp @@ -36,6 +36,41 @@ ImportPreferencesModel::ImportPreferencesModel(QObject* parent) void ImportPreferencesModel::load() { + notationConfiguration()->styleFileImportPathChanged().onReceive(this, [this](const std::string& val) { + emit styleFileImportPathChanged(QString::fromStdString(val)); + }); + + oveConfiguration()->importOvertureCharsetChanged().onReceive(this, [this](const std::string& val) { + emit currentOvertureCharsetChanged(QString::fromStdString(val)); + }); + + musicXmlConfiguration()->importLayoutChanged().onReceive(this, [this](bool val) { + emit importLayoutChanged(val); + }); + + musicXmlConfiguration()->importBreaksChanged().onReceive(this, [this](bool val) { + emit importBreaksChanged(val); + }); + + musicXmlConfiguration()->needUseDefaultFontChanged().onReceive(this, [this](bool val) { + emit needUseDefaultFontChanged(val); + }); + + musicXmlConfiguration()->inferTextTypeChanged().onReceive(this, [this](bool val) { + emit inferTextTypeChanged(val); + }); + + midiImportExportConfiguration()->midiShortestNoteChanged().onReceive(this, [this](int val) { + emit currentShortestNoteChanged(val); + }); + + meiConfiguration()->meiImportLayoutChanged().onReceive(this, [this](bool val) { + emit meiImportLayoutChanged(val); + }); + + musicXmlConfiguration()->needAskAboutApplyingNewStyleChanged().onReceive(this, [this](bool val) { + emit needAskAboutApplyingNewStyleChanged(val); + }); } QVariantList ImportPreferencesModel::charsets() const diff --git a/src/appshell/view/preferences/noteinputpreferencesmodel.cpp b/src/appshell/view/preferences/noteinputpreferencesmodel.cpp index 5810ddc5f4496..66effda0324f6 100644 --- a/src/appshell/view/preferences/noteinputpreferencesmodel.cpp +++ b/src/appshell/view/preferences/noteinputpreferencesmodel.cpp @@ -36,6 +36,38 @@ void NoteInputPreferencesModel::load() playbackConfiguration()->playNotesWhenEditingChanged().onNotify(this, [this]() { emit playNotesWhenEditingChanged(playNotesWhenEditing()); }); + + shortcutsConfiguration()->advanceToNextNoteOnKeyReleaseChanged().onReceive(this, [this](bool value) { + emit advanceToNextNoteOnKeyReleaseChanged(value); + }); + + notationConfiguration()->colorNotesOutsideOfUsablePitchRangeChanged().onReceive(this, [this](bool value) { + emit colorNotesOutsideOfUsablePitchRangeChanged(value); + }); + + notationConfiguration()->warnGuitarBendsChanged().onReceive(this, [this](bool value) { + emit warnGuitarBendsChanged(value); + }); + + notationConfiguration()->delayBetweenNotesInRealTimeModeMillisecondsChanged().onReceive(this, [this](int value) { + emit delayBetweenNotesInRealTimeModeMillisecondsChanged(value); + }); + + notationConfiguration()->notePlayDurationMillisecondsChanged().onReceive(this, [this](int value) { + emit notePlayDurationMillisecondsChanged(value); + }); + + playbackConfiguration()->playChordWhenEditingChanged().onReceive(this, [this](bool value) { + emit playChordWhenEditingChanged(value); + }); + + playbackConfiguration()->playHarmonyWhenEditingChanged().onReceive(this, [this](bool value) { + emit playChordSymbolWhenEditingChanged(value); + }); + + engravingConfiguration()->dynamicsApplyToAllVoicesChanged().onReceive(this, [this](bool value) { + emit dynamicsApplyToAllVoicesChanged(value); + }); } bool NoteInputPreferencesModel::advanceToNextNoteOnKeyRelease() const diff --git a/src/appshell/view/preferences/preferencesmodel.cpp b/src/appshell/view/preferences/preferencesmodel.cpp index 41ce6e5ccd065..da8b85e5c6848 100644 --- a/src/appshell/view/preferences/preferencesmodel.cpp +++ b/src/appshell/view/preferences/preferencesmodel.cpp @@ -207,12 +207,33 @@ void PreferencesModel::load(const QString& currentPageId) endResetModel(); } +bool PreferencesModel::askForConfirmationOfPreferencesReset() +{ + std::string title = muse::trc("appshell", "Are you sure you want to reset preferences?"); + std::string question = muse::trc("appshell", "This action will reset all your app preferences and delete all custom shortcuts. " + "It will not delete any of your scores.\n\n" + "This action cannot be undone."); + + muse::IInteractive::ButtonData cancelBtn = interactive()->buttonData(muse::IInteractive::Button::Cancel); + muse::IInteractive::ButtonData resetBtn = interactive()->buttonData(muse::IInteractive::Button::Reset); + cancelBtn.accent = true; + + muse::IInteractive::Result result = interactive()->warning(title, question, { cancelBtn, resetBtn }, cancelBtn.btn, + { muse::IInteractive::Option::WithIcon }, + muse::trc("appshell", "Reset preferences")); + return result.standardButton() == muse::IInteractive::Button::Reset; +} + void PreferencesModel::resetFactorySettings() { static constexpr bool KEEP_DEFAULT_SETTINGS = true; QApplication::setOverrideCursor(Qt::WaitCursor); QApplication::processEvents(); configuration()->revertToFactorySettings(KEEP_DEFAULT_SETTINGS); + + // Unreset the "First Launch Completed" setting so the first-time launch wizard does not appear. + configuration()->setHasCompletedFirstLaunchSetup(true); + configuration()->startEditSettings(); QApplication::restoreOverrideCursor(); } diff --git a/src/appshell/view/preferences/preferencesmodel.h b/src/appshell/view/preferences/preferencesmodel.h index 64497b6fa2b59..91abb00ffe9b3 100644 --- a/src/appshell/view/preferences/preferencesmodel.h +++ b/src/appshell/view/preferences/preferencesmodel.h @@ -31,6 +31,7 @@ #include "iappshellconfiguration.h" #include "preferencepageitem.h" +#include "iinteractive.h" namespace mu::appshell { class PreferencesModel : public QAbstractItemModel, public muse::Injectable @@ -42,6 +43,7 @@ class PreferencesModel : public QAbstractItemModel, public muse::Injectable muse::Inject dispatcher = { this }; muse::Inject configuration = { this }; muse::Inject actionsRegister = { this }; + muse::Inject interactive = { this }; public: explicit PreferencesModel(QObject* parent = nullptr); @@ -57,6 +59,7 @@ class PreferencesModel : public QAbstractItemModel, public muse::Injectable QString currentPageId() const; Q_INVOKABLE void load(const QString& currentPageId); + Q_INVOKABLE bool askForConfirmationOfPreferencesReset(); Q_INVOKABLE void resetFactorySettings(); Q_INVOKABLE void apply(); Q_INVOKABLE void cancel(); diff --git a/src/appshell/view/preferences/scorepreferencesmodel.cpp b/src/appshell/view/preferences/scorepreferencesmodel.cpp index 2df97be433e77..877398a31ada4 100644 --- a/src/appshell/view/preferences/scorepreferencesmodel.cpp +++ b/src/appshell/view/preferences/scorepreferencesmodel.cpp @@ -100,6 +100,19 @@ void ScorePreferencesModel::load() }; endResetModel(); + + notationConfiguration()->scoreOrderListPathsChanged().onNotify(this, [this]() { + setPath(DefaultFileType::FirstScoreOrderList, firstScoreOrderListPath()); + setPath(DefaultFileType::SecondScoreOrderList, secondScoreOrderListPath()); + }); + + notationConfiguration()->defaultStyleFilePathChanged().onReceive(this, [this](const io::path_t& val) { + setPath(DefaultFileType::Style, val.toQString()); + }); + + notationConfiguration()->partStyleFilePathChanged().onReceive(this, [this](const io::path_t& val) { + setPath(DefaultFileType::PartStyle, val.toQString()); + }); } void ScorePreferencesModel::savePath(ScorePreferencesModel::DefaultFileType fileType, const QString& path) diff --git a/src/appshell/view/preferences/updatepreferencesmodel.cpp b/src/appshell/view/preferences/updatepreferencesmodel.cpp index c8be9ffed7a95..20b1f66191056 100644 --- a/src/appshell/view/preferences/updatepreferencesmodel.cpp +++ b/src/appshell/view/preferences/updatepreferencesmodel.cpp @@ -31,6 +31,13 @@ UpdatePreferencesModel::UpdatePreferencesModel(QObject* parent) { } +void UpdatePreferencesModel::load() +{ + updateConfiguration()->needCheckForUpdateChanged().onNotify(this, [this]() { + emit needCheckForNewAppVersionChanged(needCheckForNewAppVersion()); + }); +} + bool UpdatePreferencesModel::isAppUpdatable() const { return updateConfiguration()->isAppUpdatable(); diff --git a/src/appshell/view/preferences/updatepreferencesmodel.h b/src/appshell/view/preferences/updatepreferencesmodel.h index c367e4c41a998..a6f2f78eefcbb 100644 --- a/src/appshell/view/preferences/updatepreferencesmodel.h +++ b/src/appshell/view/preferences/updatepreferencesmodel.h @@ -24,11 +24,12 @@ #include +#include "async/asyncable.h" #include "modularity/ioc.h" #include "update/iupdateconfiguration.h" namespace mu::appshell { -class UpdatePreferencesModel : public QObject, public muse::Injectable +class UpdatePreferencesModel : public QObject, public muse::Injectable, public muse::async::Asyncable { Q_OBJECT @@ -40,6 +41,8 @@ class UpdatePreferencesModel : public QObject, public muse::Injectable public: explicit UpdatePreferencesModel(QObject* parent = nullptr); + Q_INVOKABLE void load(); + bool needCheckForNewAppVersion() const; Q_INVOKABLE bool isAppUpdatable() const; diff --git a/src/engraving/iengravingconfiguration.h b/src/engraving/iengravingconfiguration.h index 906cbd3872189..e360d43942bfc 100644 --- a/src/engraving/iengravingconfiguration.h +++ b/src/engraving/iengravingconfiguration.h @@ -44,9 +44,11 @@ class IEngravingConfiguration : MODULE_EXPORT_INTERFACE virtual muse::io::path_t defaultStyleFilePath() const = 0; virtual void setDefaultStyleFilePath(const muse::io::path_t& path) = 0; + virtual muse::async::Channel defaultStyleFilePathChanged() const = 0; virtual muse::io::path_t partStyleFilePath() const = 0; virtual void setPartStyleFilePath(const muse::io::path_t& path) = 0; + virtual muse::async::Channel partStyleFilePathChanged() const = 0; virtual SizeF defaultPageSize() const = 0; @@ -77,6 +79,7 @@ class IEngravingConfiguration : MODULE_EXPORT_INTERFACE virtual bool dynamicsApplyToAllVoices() const = 0; virtual void setDynamicsApplyToAllVoices(bool v) = 0; + virtual muse::async::Channel dynamicsApplyToAllVoicesChanged() const = 0; virtual Color formattingColor() const = 0; virtual muse::async::Channel formattingColorChanged() const = 0; diff --git a/src/engraving/internal/engravingconfiguration.cpp b/src/engraving/internal/engravingconfiguration.cpp index 9eadffcbbff8e..a171065834d00 100644 --- a/src/engraving/internal/engravingconfiguration.cpp +++ b/src/engraving/internal/engravingconfiguration.cpp @@ -73,6 +73,16 @@ void EngravingConfiguration::init() "#6038FC", // "all voices" }; + settings()->setDefaultValue(DEFAULT_STYLE_FILE_PATH, Val(muse::io::path_t())); + settings()->valueChanged(DEFAULT_STYLE_FILE_PATH).onReceive(this, [this](const Val& val) { + m_defaultStyleFilePathChanged.send(val.toPath()); + }); + + settings()->setDefaultValue(PART_STYLE_FILE_PATH, Val(muse::io::path_t())); + settings()->valueChanged(PART_STYLE_FILE_PATH).onReceive(this, [this](const Val& val) { + m_partStyleFilePathChanged.send(val.toPath()); + }); + settings()->setDefaultValue(INVERT_SCORE_COLOR, Val(false)); settings()->valueChanged(INVERT_SCORE_COLOR).onReceive(nullptr, [this](const Val&) { m_scoreInversionChanged.notify(); @@ -107,6 +117,9 @@ void EngravingConfiguration::init() VOICE_COLORS[ALL_VOICES_IDX] = VoiceColor { std::move(ALL_VOICES_COLOR), currentColor }; settings()->setDefaultValue(DYNAMICS_APPLY_TO_ALL_VOICES, Val(true)); + settings()->valueChanged(DYNAMICS_APPLY_TO_ALL_VOICES).onReceive(this, [this](const Val& val) { + m_dynamicsApplyToAllVoicesChanged.send(val.toBool()); + }); settings()->setDefaultValue(FRAME_COLOR, Val(Color("#A0A0A4").toQColor())); settings()->setDescription(FRAME_COLOR, muse::trc("engraving", "Frame color")); @@ -151,6 +164,11 @@ void EngravingConfiguration::setDefaultStyleFilePath(const muse::io::path_t& pat settings()->setSharedValue(DEFAULT_STYLE_FILE_PATH, Val(path.toStdString())); } +async::Channel EngravingConfiguration::defaultStyleFilePathChanged() const +{ + return m_defaultStyleFilePathChanged; +} + muse::io::path_t EngravingConfiguration::partStyleFilePath() const { return settings()->value(PART_STYLE_FILE_PATH).toPath(); @@ -161,6 +179,11 @@ void EngravingConfiguration::setPartStyleFilePath(const muse::io::path_t& path) settings()->setSharedValue(PART_STYLE_FILE_PATH, Val(path.toStdString())); } +async::Channel EngravingConfiguration::partStyleFilePathChanged() const +{ + return m_partStyleFilePathChanged; +} + static bool defaultPageSizeIsLetter() { // try PAPERSIZE environment variable @@ -320,6 +343,11 @@ void EngravingConfiguration::setDynamicsApplyToAllVoices(bool v) settings()->setSharedValue(DYNAMICS_APPLY_TO_ALL_VOICES, Val(v)); } +muse::async::Channel EngravingConfiguration::dynamicsApplyToAllVoicesChanged() const +{ + return m_dynamicsApplyToAllVoicesChanged; +} + muse::async::Notification EngravingConfiguration::scoreInversionChanged() const { return m_scoreInversionChanged; diff --git a/src/engraving/internal/engravingconfiguration.h b/src/engraving/internal/engravingconfiguration.h index e0c83e43dd502..596ac1531be4d 100644 --- a/src/engraving/internal/engravingconfiguration.h +++ b/src/engraving/internal/engravingconfiguration.h @@ -50,9 +50,11 @@ class EngravingConfiguration : public IEngravingConfiguration, public muse::Inje muse::io::path_t defaultStyleFilePath() const override; void setDefaultStyleFilePath(const muse::io::path_t& path) override; + muse::async::Channel defaultStyleFilePathChanged() const override; muse::io::path_t partStyleFilePath() const override; void setPartStyleFilePath(const muse::io::path_t& path) override; + muse::async::Channel partStyleFilePathChanged() const override; SizeF defaultPageSize() const override; @@ -84,6 +86,7 @@ class EngravingConfiguration : public IEngravingConfiguration, public muse::Inje bool dynamicsApplyToAllVoices() const override; void setDynamicsApplyToAllVoices(bool v) override; + muse::async::Channel dynamicsApplyToAllVoicesChanged() const override; muse::async::Notification scoreInversionChanged() const override; @@ -120,9 +123,12 @@ class EngravingConfiguration : public IEngravingConfiguration, public muse::Inje private: muse::async::Channel m_voiceColorChanged; muse::async::Notification m_scoreInversionChanged; + muse::async::Channel m_dynamicsApplyToAllVoicesChanged; muse::async::Channel m_formattingColorChanged; muse::async::Channel m_frameColorChanged; muse::async::Channel m_unlinkedColorChanged; + muse::async::Channel m_defaultStyleFilePathChanged; + muse::async::Channel m_partStyleFilePathChanged; muse::ValNt m_debuggingOptions; diff --git a/src/engraving/tests/mocks/engravingconfigurationmock.h b/src/engraving/tests/mocks/engravingconfigurationmock.h index 20dadeca9df98..6dcaf920c277a 100644 --- a/src/engraving/tests/mocks/engravingconfigurationmock.h +++ b/src/engraving/tests/mocks/engravingconfigurationmock.h @@ -34,9 +34,11 @@ class EngravingConfigurationMock : public IEngravingConfiguration MOCK_METHOD(muse::io::path_t, defaultStyleFilePath, (), (const, override)); MOCK_METHOD(void, setDefaultStyleFilePath, (const muse::io::path_t&), (override)); + MOCK_METHOD(muse::async::Channel, defaultStyleFilePathChanged, (), (const, override)); MOCK_METHOD(muse::io::path_t, partStyleFilePath, (), (const, override)); MOCK_METHOD(void, setPartStyleFilePath, (const muse::io::path_t&), (override)); + MOCK_METHOD(muse::async::Channel, partStyleFilePathChanged, (), (const, override)); MOCK_METHOD(SizeF, defaultPageSize, (), (const, override)); @@ -63,6 +65,7 @@ class EngravingConfigurationMock : public IEngravingConfiguration MOCK_METHOD(bool, dynamicsApplyToAllVoices, (), (const, override)); MOCK_METHOD(void, setDynamicsApplyToAllVoices, (bool), (override)); + MOCK_METHOD((muse::async::Channel), dynamicsApplyToAllVoicesChanged, (), (const, override)); MOCK_METHOD(bool, scoreInversionEnabled, (), (const, override)); MOCK_METHOD(void, setScoreInversionEnabled, (bool), (override)); diff --git a/src/framework/audio/audiotypes.h b/src/framework/audio/audiotypes.h index bc642358c45e8..68f4296021de1 100644 --- a/src/framework/audio/audiotypes.h +++ b/src/framework/audio/audiotypes.h @@ -69,6 +69,8 @@ using PlaybackSetupData = mpe::PlaybackSetupData; static constexpr TrackId INVALID_TRACK_ID = -1; +static constexpr char DEFAULT_DEVICE_ID[] = "default"; + #ifdef Q_OS_WIN static constexpr size_t MINIMUM_BUFFER_SIZE = 256; #else diff --git a/src/framework/audio/internal/audioconfiguration.cpp b/src/framework/audio/internal/audioconfiguration.cpp index 415be6850aa0f..6cf4681f6019d 100644 --- a/src/framework/audio/internal/audioconfiguration.cpp +++ b/src/framework/audio/internal/audioconfiguration.cpp @@ -70,6 +70,7 @@ void AudioConfiguration::init() settings()->setDefaultValue(AUDIO_API_KEY, Val("Core Audio")); + settings()->setDefaultValue(AUDIO_OUTPUT_DEVICE_ID_KEY, Val(DEFAULT_DEVICE_ID)); settings()->valueChanged(AUDIO_OUTPUT_DEVICE_ID_KEY).onReceive(nullptr, [this](const Val&) { m_audioOutputDeviceIdChanged.notify(); }); diff --git a/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp b/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp index fd1d2a2327083..3245ec240d300 100644 --- a/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp +++ b/src/framework/audio/internal/platform/jack/jackaudiodriver.cpp @@ -33,8 +33,6 @@ #include "log.h" #include "runtime.h" -static constexpr char JACK_DEFAULT_DEVICE_ID[] = "default"; - using namespace muse::audio; struct JackData @@ -88,7 +86,7 @@ void jackCleanup() JackAudioDriver::JackAudioDriver() { - m_deviceId = JACK_DEFAULT_DEVICE_ID; + m_deviceId = DEFAULT_DEVICE_ID; } JackAudioDriver::~JackAudioDriver() @@ -226,7 +224,7 @@ bool JackAudioDriver::selectOutputDevice(const AudioDeviceID& deviceId) bool JackAudioDriver::resetToDefaultOutputDevice() { - return selectOutputDevice(JACK_DEFAULT_DEVICE_ID); + return selectOutputDevice(DEFAULT_DEVICE_ID); } async::Notification JackAudioDriver::outputDeviceChanged() const @@ -237,7 +235,7 @@ async::Notification JackAudioDriver::outputDeviceChanged() const AudioDeviceList JackAudioDriver::availableOutputDevices() const { AudioDeviceList devices; - devices.push_back({ JACK_DEFAULT_DEVICE_ID, muse::trc("audio", "System default") }); + devices.push_back({ DEFAULT_DEVICE_ID, muse::trc("audio", "System default") }); return devices; } diff --git a/src/framework/audio/internal/platform/lin/linuxaudiodriver.cpp b/src/framework/audio/internal/platform/lin/linuxaudiodriver.cpp index b25417f3411f5..7c73c5975f694 100644 --- a/src/framework/audio/internal/platform/lin/linuxaudiodriver.cpp +++ b/src/framework/audio/internal/platform/lin/linuxaudiodriver.cpp @@ -34,8 +34,6 @@ #include "log.h" #include "runtime.h" -static constexpr char DEFAULT_DEVICE_ID[] = "default"; - using namespace muse; using namespace muse::audio; diff --git a/src/framework/audio/internal/platform/win/wasapiaudiodriver.cpp b/src/framework/audio/internal/platform/win/wasapiaudiodriver.cpp index 7b03f56b3a84b..c5b8f5f5da9ac 100644 --- a/src/framework/audio/internal/platform/win/wasapiaudiodriver.cpp +++ b/src/framework/audio/internal/platform/win/wasapiaudiodriver.cpp @@ -34,8 +34,6 @@ using namespace winrt; using namespace muse; using namespace muse::audio; -static constexpr char DEFAULT_DEVICE_ID[] = "default"; - inline int refTimeToSamples(const REFERENCE_TIME& t, double sampleRate) noexcept { return sampleRate * ((double)t) * 0.0000001; diff --git a/src/framework/audio/internal/platform/win/wincoreaudiodriver.cpp b/src/framework/audio/internal/platform/win/wincoreaudiodriver.cpp index 39e6c65797654..0ec65cc4b9add 100644 --- a/src/framework/audio/internal/platform/win/wincoreaudiodriver.cpp +++ b/src/framework/audio/internal/platform/win/wincoreaudiodriver.cpp @@ -82,7 +82,6 @@ void copyWavFormat(WAVEFORMATEXTENSIBLE& dest, const WAVEFORMATEX* src) noexcept static void logError(HRESULT hr); static WinCoreData* s_data = nullptr; -static constexpr char DEFAULT_DEVICE_ID[] = "default"; static IAudioDriver::Spec s_activeSpec; static HRESULT s_lastError = S_OK; diff --git a/src/framework/autobot/internal/autobotinteractive.cpp b/src/framework/autobot/internal/autobotinteractive.cpp index dea9a4c33b22e..0dede6f16c2ba 100644 --- a/src/framework/autobot/internal/autobotinteractive.cpp +++ b/src/framework/autobot/internal/autobotinteractive.cpp @@ -37,15 +37,16 @@ std::shared_ptr AutobotInteractive::realInteractive() const } IInteractive::Result AutobotInteractive::question(const std::string& title, const std::string& text, const Buttons& buttons, - const Button& def, const Options& options) const + const Button& def, const Options& options, + const std::string& dialogTitle) const { - return m_real->question(title, text, buttons, def, options); + return m_real->question(title, text, buttons, def, options, dialogTitle); } IInteractive::Result AutobotInteractive::question(const std::string& title, const Text& text, const ButtonDatas& buttons, - int defBtn, const Options& options) const + int defBtn, const Options& options, const std::string& dialogTitle) const { - return m_real->question(title, text, buttons, defBtn, options); + return m_real->question(title, text, buttons, defBtn, options, dialogTitle); } IInteractive::ButtonData AutobotInteractive::buttonData(Button b) const @@ -54,52 +55,53 @@ IInteractive::ButtonData AutobotInteractive::buttonData(Button b) const } IInteractive::Result AutobotInteractive::info(const std::string& title, const std::string& text, const Buttons& buttons, - int defBtn, const Options& options) const + int defBtn, const Options& options, const std::string& dialogTitle) const { - return m_real->info(title, text, buttons, defBtn, options); + return m_real->info(title, text, buttons, defBtn, options, dialogTitle); } IInteractive::Result AutobotInteractive::info(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn, - const Options& options) const + const Options& options, const std::string& dialogTitle) const { - return m_real->info(title, text, buttons, defBtn, options); + return m_real->info(title, text, buttons, defBtn, options, dialogTitle); } IInteractive::Result AutobotInteractive::warning(const std::string& title, const std::string& text, const Buttons& buttons, - const Button& def, const Options& options) const + const Button& def, const Options& options, const std::string& dialogTitle) const { - return m_real->warning(title, text, buttons, def, options); + return m_real->warning(title, text, buttons, def, options, dialogTitle); } IInteractive::Result AutobotInteractive::warning(const std::string& title, const Text& text, const ButtonDatas& buttons, - int defBtn, const Options& options) const + int defBtn, const Options& options, const std::string& dialogTitle) const { - return m_real->warning(title, text, buttons, defBtn, options); + return m_real->warning(title, text, buttons, defBtn, options, dialogTitle); } IInteractive::Result AutobotInteractive::warning(const std::string& title, const Text& text, const std::string& detailedText, const ButtonDatas& buttons, int defBtn, - const Options& options) const + const Options& options, const std::string& dialogTitle) const { - return m_real->warning(title, text, detailedText, buttons, defBtn, options); + return m_real->warning(title, text, detailedText, buttons, defBtn, options, dialogTitle); } IInteractive::Result AutobotInteractive::error(const std::string& title, const std::string& text, const Buttons& buttons, - const Button& def, const Options& options) const + const Button& def, const Options& options, const std::string& dialogTitle) const { - return m_real->error(title, text, buttons, def, options); + return m_real->error(title, text, buttons, def, options, dialogTitle); } IInteractive::Result AutobotInteractive::error(const std::string& title, const Text& text, const ButtonDatas& buttons, - int defBtn, const Options& options) const + int defBtn, const Options& options, const std::string& dialogTitle) const { - return m_real->error(title, text, buttons, defBtn, options); + return m_real->error(title, text, buttons, defBtn, options, dialogTitle); } IInteractive::Result AutobotInteractive::error(const std::string& title, const Text& text, const std::string& detailedText, - const ButtonDatas& buttons, int defBtn, const Options& options) const + const ButtonDatas& buttons, int defBtn, const Options& options, + const std::string& dialogTitle) const { - return m_real->error(title, text, detailedText, buttons, defBtn, options); + return m_real->error(title, text, detailedText, buttons, defBtn, options, dialogTitle); } Ret AutobotInteractive::showProgress(const std::string& title, Progress* progress) const diff --git a/src/framework/autobot/internal/autobotinteractive.h b/src/framework/autobot/internal/autobotinteractive.h index 366df6efc2622..ec61c43f1c904 100644 --- a/src/framework/autobot/internal/autobotinteractive.h +++ b/src/framework/autobot/internal/autobotinteractive.h @@ -36,39 +36,39 @@ class AutobotInteractive : public IInteractive std::shared_ptr realInteractive() const; Result question(const std::string& title, const std::string& text, const Buttons& buttons, const Button& def = Button::NoButton, - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; Result question(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn = int(Button::NoButton), - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; ButtonData buttonData(Button b) const override; // info Result info(const std::string& title, const std::string& text, const Buttons& buttons = {}, int defBtn = int(Button::NoButton), - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; Result info(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn = int(Button::NoButton), - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; // warning Result warning(const std::string& title, const std::string& text, const Buttons& buttons = {}, const Button& def = Button::NoButton, - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; Result warning(const std::string& title, const Text& text, const ButtonDatas& buttons = {}, int defBtn = int(Button::NoButton), - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; Result warning(const std::string& title, const Text& text, const std::string& detailedText, const ButtonDatas& buttons = {}, - int defBtn = int(Button::NoButton), const Options& options = {}) const override; + int defBtn = int(Button::NoButton), const Options& options = {}, const std::string& dialogTitle = "") const override; // error Result error(const std::string& title, const std::string& text, const Buttons& buttons = {}, const Button& def = Button::NoButton, - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; Result error(const std::string& title, const Text& text, const ButtonDatas& buttons = {}, int defBtn = int(Button::NoButton), - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; Result error(const std::string& title, const Text& text, const std::string& detailedText, const ButtonDatas& buttons = {}, - int defBtn = int(Button::NoButton), const Options& options = {}) const override; + int defBtn = int(Button::NoButton), const Options& options = {}, const std::string& dialogTitle = "") const override; // progress Ret showProgress(const std::string& title, Progress* progress) const override; diff --git a/src/framework/global/iinteractive.h b/src/framework/global/iinteractive.h index a6a7bf0b08497..8c05b32362d79 100644 --- a/src/framework/global/iinteractive.h +++ b/src/framework/global/iinteractive.h @@ -146,39 +146,43 @@ class IInteractive : MODULE_EXPORT_INTERFACE DECLARE_FLAGS(Options, Option) virtual Result question(const std::string& title, const std::string& text, const Buttons& buttons, const Button& def = Button::NoButton, - const Options& options = {}) const = 0; + const Options& options = {}, const std::string& dialogTitle = "") const = 0; virtual Result question(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn = int(Button::NoButton), - const Options& options = {}) const = 0; + const Options& options = {}, const std::string& dialogTitle = "") const = 0; virtual ButtonData buttonData(Button b) const = 0; // info virtual Result info(const std::string& title, const std::string& text, const Buttons& buttons = {}, int defBtn = int(Button::NoButton), - const Options& options = {}) const = 0; + const Options& options = {}, const std::string& dialogTitle = "") const = 0; virtual Result info(const std::string& title, const Text& text, const ButtonDatas& buttons = {}, int defBtn = int(Button::NoButton), - const Options& options = {}) const = 0; + const Options& options = {}, const std::string& dialogTitle = "") const = 0; // warning virtual Result warning(const std::string& title, const std::string& text, const Buttons& buttons = {}, - const Button& def = Button::NoButton, const Options& options = { WithIcon }) const = 0; + const Button& def = Button::NoButton, const Options& options = { WithIcon }, + const std::string& dialogTitle = "") const = 0; virtual Result warning(const std::string& title, const Text& text, const ButtonDatas& buttons = {}, int defBtn = int(Button::NoButton), - const Options& options = { WithIcon }) const = 0; + const Options& options = { WithIcon }, const std::string& dialogTitle = "") const = 0; virtual Result warning(const std::string& title, const Text& text, const std::string& detailedText, const ButtonDatas& buttons = {}, - int defBtn = int(Button::NoButton), const Options& options = { WithIcon }) const = 0; + int defBtn = int(Button::NoButton), const Options& options = { WithIcon }, + const std::string& dialogTitle = "") const = 0; // error virtual Result error(const std::string& title, const std::string& text, const Buttons& buttons = {}, - const Button& def = Button::NoButton, const Options& options = { WithIcon }) const = 0; + const Button& def = Button::NoButton, const Options& options = { WithIcon }, + const std::string& dialogTitle = "") const = 0; virtual Result error(const std::string& title, const Text& text, const ButtonDatas& buttons = {}, int defBtn = int(Button::NoButton), - const Options& options = { WithIcon }) const = 0; + const Options& options = { WithIcon }, const std::string& dialogTitle = "") const = 0; virtual Result error(const std::string& title, const Text& text, const std::string& detailedText, const ButtonDatas& buttons = {}, - int defBtn = int(Button::NoButton), const Options& options = { WithIcon }) const = 0; + int defBtn = int(Button::NoButton), const Options& options = { WithIcon }, + const std::string& dialogTitle = "") const = 0; // progress virtual Ret showProgress(const std::string& title, Progress* progress) const = 0; diff --git a/src/framework/global/internal/interactive.cpp b/src/framework/global/internal/interactive.cpp index b156b54b2633f..7298e6b18707c 100644 --- a/src/framework/global/internal/interactive.cpp +++ b/src/framework/global/internal/interactive.cpp @@ -76,15 +76,16 @@ static QString filterToString(const std::vector& filter) IInteractive::Result Interactive::question(const std::string& title, const std::string& text, const Buttons& buttons, const Button& def, - const Options& options) const + const Options& options, + const std::string& dialogTitle) const { - return question(title, Text(text), buttonDataList(buttons), int(def), options); + return question(title, Text(text), buttonDataList(buttons), int(def), options, dialogTitle); } IInteractive::Result Interactive::question(const std::string& title, const Text& text, const ButtonDatas& btns, int defBtn, - const Options& options) const + const Options& options, const std::string& dialogTitle) const { - return standardDialogResult(provider()->question(title, text, btns, defBtn, options)); + return standardDialogResult(provider()->question(title, text, btns, defBtn, options, dialogTitle)); } IInteractive::ButtonData Interactive::buttonData(Button b) const @@ -126,56 +127,58 @@ IInteractive::ButtonData Interactive::buttonData(Button b) const IInteractive::Result Interactive::info(const std::string& title, const std::string& text, const Buttons& buttons, int defBtn, - const Options& options) const + const Options& options, + const std::string& dialogTitle) const { - return standardDialogResult(provider()->info(title, text, buttonDataList(buttons), defBtn, options)); + return standardDialogResult(provider()->info(title, text, buttonDataList(buttons), defBtn, options, dialogTitle)); } IInteractive::Result Interactive::info(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn, - const Options& options) const + const Options& options, const std::string& dialogTitle) const { - return standardDialogResult(provider()->info(title, text, buttons, defBtn, options)); + return standardDialogResult(provider()->info(title, text, buttons, defBtn, options, dialogTitle)); } Interactive::Result Interactive::warning(const std::string& title, const std::string& text, const Buttons& buttons, const Button& defBtn, - const Options& options) const + const Options& options, const std::string& dialogTitle) const { - return standardDialogResult(provider()->warning(title, text, {}, buttonDataList(buttons), int(defBtn), options)); + return standardDialogResult(provider()->warning(title, text, {}, buttonDataList(buttons), int(defBtn), options, dialogTitle)); } IInteractive::Result Interactive::warning(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn, - const Options& options) const + const Options& options, + const std::string& dialogTitle) const { - return standardDialogResult(provider()->warning(title, text, {}, buttons, defBtn, options)); + return standardDialogResult(provider()->warning(title, text, {}, buttons, defBtn, options, dialogTitle)); } IInteractive::Result Interactive::warning(const std::string& title, const Text& text, const std::string& detailedText, const ButtonDatas& buttons, int defBtn, - const Options& options) const + const Options& options, const std::string& dialogTitle) const { - return standardDialogResult(provider()->warning(title, text, detailedText, buttons, defBtn, options)); + return standardDialogResult(provider()->warning(title, text, detailedText, buttons, defBtn, options, dialogTitle)); } IInteractive::Result Interactive::error(const std::string& title, const std::string& text, const Buttons& buttons, const Button& defBtn, - const Options& options) const + const Options& options, const std::string& dialogTitle) const { - return standardDialogResult(provider()->error(title, text, {}, buttonDataList(buttons), int(defBtn), options)); + return standardDialogResult(provider()->error(title, text, {}, buttonDataList(buttons), int(defBtn), options, dialogTitle)); } IInteractive::Result Interactive::error(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn, - const Options& options) const + const Options& options, const std::string& dialogTitle) const { - return standardDialogResult(provider()->error(title, text, {}, buttons, defBtn, options)); + return standardDialogResult(provider()->error(title, text, {}, buttons, defBtn, options, dialogTitle)); } IInteractive::Result Interactive::error(const std::string& title, const Text& text, const std::string& detailedText, const ButtonDatas& buttons, int defBtn, - const Options& options) const + const Options& options, const std::string& dialogTitle) const { - return standardDialogResult(provider()->error(title, text, detailedText, buttons, defBtn, options)); + return standardDialogResult(provider()->error(title, text, detailedText, buttons, defBtn, options, dialogTitle)); } Ret Interactive::showProgress(const std::string& title, Progress* progress) const diff --git a/src/framework/global/internal/interactive.h b/src/framework/global/internal/interactive.h index 9710c6a7c9aaa..fc312ea55fd73 100644 --- a/src/framework/global/internal/interactive.h +++ b/src/framework/global/internal/interactive.h @@ -45,39 +45,41 @@ class Interactive : public IInteractive, public Injectable, public async::Asynca // question Result question(const std::string& title, const std::string& text, const Buttons& buttons, const Button& def = Button::NoButton, - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; Result question(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn = int(Button::NoButton), - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; ButtonData buttonData(Button b) const override; // info Result info(const std::string& title, const std::string& text, const Buttons& buttons, int defBtn = int(Button::NoButton), - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; Result info(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn = int(Button::NoButton), - const Options& options = {}) const override; + const Options& options = {}, const std::string& dialogTitle = "") const override; // warning Result warning(const std::string& title, const std::string& text, const Buttons& buttons, const Button& def = Button::NoButton, - const Options& options = { WithIcon }) const override; + const Options& options = { WithIcon }, const std::string& dialogTitle = "") const override; Result warning(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn = int(Button::NoButton), - const Options& options = { WithIcon }) const override; + const Options& options = { WithIcon }, const std::string& dialogTitle = "") const override; Result warning(const std::string& title, const Text& text, const std::string& detailedText, const ButtonDatas& buttons, - int defBtn = int(Button::NoButton), const Options& options = { WithIcon }) const override; + int defBtn = int(Button::NoButton), const Options& options = { WithIcon }, + const std::string& dialogTitle = "") const override; // error Result error(const std::string& title, const std::string& text, const Buttons& buttons, const Button& def = Button::NoButton, - const Options& options = { WithIcon }) const override; + const Options& options = { WithIcon }, const std::string& dialogTitle = "") const override; Result error(const std::string& title, const Text& text, const ButtonDatas& buttons, int defBtn = int(Button::NoButton), - const Options& options = { WithIcon }) const override; + const Options& options = { WithIcon }, const std::string& dialogTitle = "") const override; Result error(const std::string& title, const Text& text, const std::string& detailedText, const ButtonDatas& buttons, - int defBtn = int(Button::NoButton), const Options& options = { WithIcon }) const override; + int defBtn = int(Button::NoButton), const Options& options = { WithIcon }, + const std::string& dialogTitle = "") const override; // progress Ret showProgress(const std::string& title, Progress* progress) const override; diff --git a/src/framework/global/settings.cpp b/src/framework/global/settings.cpp index 2b65d02e7f928..1de6648e2b3ff 100644 --- a/src/framework/global/settings.cpp +++ b/src/framework/global/settings.cpp @@ -95,6 +95,13 @@ void Settings::reset(bool keepDefaultSettings, bool notifyAboutChanges) m_settings->clear(); m_isTransactionStarted = false; + + std::vector locallyAddedKeys; + for (auto it = m_localSettings.begin(); it != m_localSettings.end(); ++it) { + if (m_items.count(it->first) == 0) { + locallyAddedKeys.push_back(it->first); + } + } m_localSettings.clear(); if (!keepDefaultSettings) { @@ -107,11 +114,19 @@ void Settings::reset(bool keepDefaultSettings, bool notifyAboutChanges) } for (auto it = m_items.begin(); it != m_items.end(); ++it) { + if (it->second.value == it->second.defaultValue) { + continue; + } + it->second.value = it->second.defaultValue; Channel& channel = findChannel(it->first); channel.send(it->second.value); } + for (auto it = locallyAddedKeys.cbegin(); it != locallyAddedKeys.cend(); ++it) { + Channel& channel = findChannel(*it); + channel.send(Val()); + } } static Val compat_QVariantToVal(const QVariant& var) diff --git a/src/framework/global/tests/mocks/interactivemock.h b/src/framework/global/tests/mocks/interactivemock.h index 5040e6ae18f57..aacee077e1d69 100644 --- a/src/framework/global/tests/mocks/interactivemock.h +++ b/src/framework/global/tests/mocks/interactivemock.h @@ -30,25 +30,31 @@ namespace muse { class InteractiveMock : public IInteractive { public: - MOCK_METHOD(Result, question, (const std::string&, const std::string&, const Buttons&, const Button&, const Options&), - (const, override)); - MOCK_METHOD(Result, question, (const std::string&, const Text&, const ButtonDatas&, int, const Options&), (const, override)); + MOCK_METHOD(Result, question, (const std::string&, const std::string&, const Buttons&, const Button&, const Options&, + const std::string&), (const, override)); + MOCK_METHOD(Result, question, (const std::string&, const Text&, const ButtonDatas&, int, const Options&, + const std::string&), (const, override)); MOCK_METHOD(ButtonData, buttonData, (Button), (const, override)); - MOCK_METHOD(Result, info, (const std::string&, const std::string&, const Buttons&, int, const Options&), (const, override)); - MOCK_METHOD(Result, info, (const std::string&, const Text&, const ButtonDatas&, int, const Options&), (const, override)); - - MOCK_METHOD(Result, warning, (const std::string&, const std::string&, const Buttons&, const Button&, const Options&), - (const, override)); - MOCK_METHOD(Result, warning, (const std::string&, const Text&, const ButtonDatas&, int, const Options&), (const, override)); - MOCK_METHOD(Result, warning, (const std::string&, const Text&, const std::string&, const ButtonDatas&, int, const Options&), - (const, override)); - - MOCK_METHOD(Result, error, (const std::string&, const std::string&, const Buttons&, const Button&, const Options&), (const, override)); - MOCK_METHOD(Result, error, (const std::string&, const Text&, const ButtonDatas&, int, const Options&), (const, override)); - MOCK_METHOD(Result, error, (const std::string&, const Text&, const std::string&, const ButtonDatas&, int, const Options&), - (const, override)); + MOCK_METHOD(Result, info, (const std::string&, const std::string&, const Buttons&, int, const Options&, + const std::string&), (const, override)); + MOCK_METHOD(Result, info, (const std::string&, const Text&, const ButtonDatas&, int, const Options&, + const std::string&), (const, override)); + + MOCK_METHOD(Result, warning, (const std::string&, const std::string&, const Buttons&, const Button&, const Options&, + const std::string&), (const, override)); + MOCK_METHOD(Result, warning, (const std::string&, const Text&, const ButtonDatas&, int, const Options&, + const std::string&), (const, override)); + MOCK_METHOD(Result, warning, (const std::string&, const Text&, const std::string&, const ButtonDatas&, int, const Options&, + const std::string&), (const, override)); + + MOCK_METHOD(Result, error, (const std::string&, const std::string&, const Buttons&, const Button&, const Options&, + const std::string&), (const, override)); + MOCK_METHOD(Result, error, (const std::string&, const Text&, const ButtonDatas&, int, const Options&, + const std::string&), (const, override)); + MOCK_METHOD(Result, error, (const std::string&, const Text&, const std::string&, const ButtonDatas&, int, const Options&, + const std::string&), (const, override)); MOCK_METHOD(Ret, showProgress, (const std::string&, Progress*), (const, override)); diff --git a/src/framework/languages/internal/languagesservice.cpp b/src/framework/languages/internal/languagesservice.cpp index 3f1197fe6b9cb..b429fb1bdbd4c 100644 --- a/src/framework/languages/internal/languagesservice.cpp +++ b/src/framework/languages/internal/languagesservice.cpp @@ -64,9 +64,14 @@ void LanguagesService::init() ValCh languageCode = configuration()->currentLanguageCode(); setCurrentLanguage(languageCode.val); - languageCode.ch.onReceive(this, [this](const QString&) { + // Remember the active language code so the "Restart required" text can go away if the language + // is changed and later reverted in the same session. Cannot use m_currentLanguage.code + // because m_currentLanguage holds the effective language: if the language code is "system", + // m_currentLanguage will hold "en-us" for example (whatever the system is set to). + QString activeLanguageCode = languageCode.val; + languageCode.ch.onReceive(this, [this, activeLanguageCode](const QString& newLanguageCode) { //! NOTE To change the language at the moment, a restart is required - m_needRestartToApplyLanguageChange = true; + m_needRestartToApplyLanguageChange = newLanguageCode != activeLanguageCode; m_needRestartToApplyLanguageChangeChanged.send(m_needRestartToApplyLanguageChange); }); diff --git a/src/framework/midi/imidiconfiguration.h b/src/framework/midi/imidiconfiguration.h index 4540699ac7b23..b49e9579a517b 100644 --- a/src/framework/midi/imidiconfiguration.h +++ b/src/framework/midi/imidiconfiguration.h @@ -41,6 +41,7 @@ class IMidiConfiguration : MODULE_EXPORT_INTERFACE virtual bool useRemoteControl() const = 0; virtual void setUseRemoteControl(bool value) = 0; + virtual async::Channel useRemoteControlChanged() const = 0; virtual MidiDeviceID midiInputDeviceId() const = 0; virtual void setMidiInputDeviceId(const MidiDeviceID& deviceId) = 0; @@ -52,6 +53,7 @@ class IMidiConfiguration : MODULE_EXPORT_INTERFACE virtual bool useMIDI20Output() const = 0; virtual void setUseMIDI20Output(bool use) = 0; + virtual async::Channel useMIDI20OutputChanged() const = 0; }; } diff --git a/src/framework/midi/internal/midiconfiguration.cpp b/src/framework/midi/internal/midiconfiguration.cpp index a09ee75835165..2cbf8f6f0ffb5 100644 --- a/src/framework/midi/internal/midiconfiguration.cpp +++ b/src/framework/midi/internal/midiconfiguration.cpp @@ -38,8 +38,11 @@ static const Settings::Key USE_MIDI20_OUTPUT_KEY(module_name, "io/midi/useMIDI20 void MidiConfiguration::init() { settings()->setDefaultValue(USE_REMOTE_CONTROL_KEY, Val(true)); + settings()->valueChanged(USE_REMOTE_CONTROL_KEY).onReceive(this, [this](const Val& val) { + m_useRemoteControlChanged.send(val.toBool()); + }); - settings()->setDefaultValue(MIDI_INPUT_DEVICE_ID, Val("")); + settings()->setDefaultValue(MIDI_INPUT_DEVICE_ID, Val(NONE_DEVICE_ID)); settings()->valueChanged(MIDI_INPUT_DEVICE_ID).onReceive(nullptr, [this](const Val&) { m_midiInputDeviceIdChanged.notify(); }); @@ -50,6 +53,9 @@ void MidiConfiguration::init() }); settings()->setDefaultValue(USE_MIDI20_OUTPUT_KEY, Val(true)); + settings()->valueChanged(USE_MIDI20_OUTPUT_KEY).onReceive(this, [this](const Val& val) { + m_useMIDI20OutputChanged.send(val.toBool()); + }); } bool MidiConfiguration::midiPortIsAvalaible() const @@ -67,6 +73,11 @@ void MidiConfiguration::setUseRemoteControl(bool value) settings()->setSharedValue(USE_REMOTE_CONTROL_KEY, Val(value)); } +async::Channel MidiConfiguration::useRemoteControlChanged() const +{ + return m_useRemoteControlChanged; +} + MidiDeviceID MidiConfiguration::midiInputDeviceId() const { return settings()->value(MIDI_INPUT_DEVICE_ID).toString(); @@ -106,3 +117,8 @@ void MidiConfiguration::setUseMIDI20Output(bool use) { settings()->setSharedValue(USE_MIDI20_OUTPUT_KEY, Val(use)); } + +async::Channel MidiConfiguration::useMIDI20OutputChanged() const +{ + return m_useMIDI20OutputChanged; +} diff --git a/src/framework/midi/internal/midiconfiguration.h b/src/framework/midi/internal/midiconfiguration.h index 43cc0badb0ad9..d556aef70ebf4 100644 --- a/src/framework/midi/internal/midiconfiguration.h +++ b/src/framework/midi/internal/midiconfiguration.h @@ -23,9 +23,10 @@ #define MUSE_MIDI_MIDICONFIGURATION_H #include "../imidiconfiguration.h" +#include "async/asyncable.h" namespace muse::midi { -class MidiConfiguration : public IMidiConfiguration +class MidiConfiguration : public IMidiConfiguration, public async::Asyncable { public: void init(); @@ -34,6 +35,7 @@ class MidiConfiguration : public IMidiConfiguration bool useRemoteControl() const override; void setUseRemoteControl(bool value) override; + async::Channel useRemoteControlChanged() const override; MidiDeviceID midiInputDeviceId() const override; void setMidiInputDeviceId(const MidiDeviceID& deviceId) override; @@ -45,10 +47,13 @@ class MidiConfiguration : public IMidiConfiguration bool useMIDI20Output() const override; void setUseMIDI20Output(bool use) override; + async::Channel useMIDI20OutputChanged() const override; private: async::Notification m_midiInputDeviceIdChanged; async::Notification m_midiOutputDeviceIdChanged; + async::Channel m_useRemoteControlChanged; + async::Channel m_useMIDI20OutputChanged; }; } diff --git a/src/framework/shortcuts/internal/shortcutsconfiguration.cpp b/src/framework/shortcuts/internal/shortcutsconfiguration.cpp index d20f564e1f713..34828fb40852e 100644 --- a/src/framework/shortcuts/internal/shortcutsconfiguration.cpp +++ b/src/framework/shortcuts/internal/shortcutsconfiguration.cpp @@ -40,6 +40,9 @@ void ShortcutsConfiguration::init() m_config = ConfigReader::read(":/configs/shortcuts.cfg"); settings()->setDefaultValue(ADVANCE_TO_NEXT_NOTE_ON_KEY_RELEASE, Val(true)); + settings()->valueChanged(ADVANCE_TO_NEXT_NOTE_ON_KEY_RELEASE).onReceive(this, [this](const Val& val) { + m_advanceToNextNoteOnKeyReleaseChanged.send(val.toBool()); + }); } QString ShortcutsConfiguration::currentKeyboardLayout() const @@ -83,3 +86,8 @@ void ShortcutsConfiguration::setAdvanceToNextNoteOnKeyRelease(bool value) { settings()->setSharedValue(ADVANCE_TO_NEXT_NOTE_ON_KEY_RELEASE, Val(value)); } + +muse::async::Channel ShortcutsConfiguration::advanceToNextNoteOnKeyReleaseChanged() const +{ + return m_advanceToNextNoteOnKeyReleaseChanged; +} diff --git a/src/framework/shortcuts/internal/shortcutsconfiguration.h b/src/framework/shortcuts/internal/shortcutsconfiguration.h index 00b426d406995..dfa2cf1478fb9 100644 --- a/src/framework/shortcuts/internal/shortcutsconfiguration.h +++ b/src/framework/shortcuts/internal/shortcutsconfiguration.h @@ -51,8 +51,11 @@ class ShortcutsConfiguration : public IShortcutsConfiguration, public Injectable bool advanceToNextNoteOnKeyRelease() const override; void setAdvanceToNextNoteOnKeyRelease(bool value) override; + virtual muse::async::Channel advanceToNextNoteOnKeyReleaseChanged() const override; private: Config m_config; + + muse::async::Channel m_advanceToNextNoteOnKeyReleaseChanged; }; } diff --git a/src/framework/shortcuts/ishortcutsconfiguration.h b/src/framework/shortcuts/ishortcutsconfiguration.h index a00e63fa80211..d7910667b22fc 100644 --- a/src/framework/shortcuts/ishortcutsconfiguration.h +++ b/src/framework/shortcuts/ishortcutsconfiguration.h @@ -44,6 +44,7 @@ class IShortcutsConfiguration : MODULE_EXPORT_INTERFACE virtual bool advanceToNextNoteOnKeyRelease() const = 0; virtual void setAdvanceToNextNoteOnKeyRelease(bool value) = 0; + virtual muse::async::Channel advanceToNextNoteOnKeyReleaseChanged() const = 0; }; } diff --git a/src/framework/shortcuts/view/mididevicemappingmodel.cpp b/src/framework/shortcuts/view/mididevicemappingmodel.cpp index 6cec27a1c9069..4a9e6d405a13f 100644 --- a/src/framework/shortcuts/view/mididevicemappingmodel.cpp +++ b/src/framework/shortcuts/view/mididevicemappingmodel.cpp @@ -124,6 +124,10 @@ QHash MidiDeviceMappingModel::roleNames() const void MidiDeviceMappingModel::load() { + midiConfiguration()->useRemoteControlChanged().onReceive(this, [this](bool val) { + emit useRemoteControlChanged(val); + }); + beginResetModel(); m_midiMappings.clear(); diff --git a/src/framework/stubs/midi/midiconfigurationstub.cpp b/src/framework/stubs/midi/midiconfigurationstub.cpp index e9205e3698eb0..b80255b0d3f27 100644 --- a/src/framework/stubs/midi/midiconfigurationstub.cpp +++ b/src/framework/stubs/midi/midiconfigurationstub.cpp @@ -38,6 +38,12 @@ void MidiConfigurationStub::setUseRemoteControl(bool) { } +async::Channel MidiConfigurationStub::useRemoteControlChanged() const +{ + static async::Channel ch; + return ch; +} + MidiDeviceID MidiConfigurationStub::midiInputDeviceId() const { return MidiDeviceID(); @@ -76,3 +82,9 @@ bool MidiConfigurationStub::useMIDI20Output() const void MidiConfigurationStub::setUseMIDI20Output(bool) { } + +async::Channel MidiConfigurationStub::useMIDI20OutputChanged() const +{ + static async::Channel ch; + return ch; +} diff --git a/src/framework/stubs/midi/midiconfigurationstub.h b/src/framework/stubs/midi/midiconfigurationstub.h index 1df8898cb077a..277f8e120c239 100644 --- a/src/framework/stubs/midi/midiconfigurationstub.h +++ b/src/framework/stubs/midi/midiconfigurationstub.h @@ -34,6 +34,7 @@ class MidiConfigurationStub : public IMidiConfiguration bool useRemoteControl() const override; void setUseRemoteControl(bool value) override; + async::Channel useRemoteControlChanged() const override; MidiDeviceID midiInputDeviceId() const override; void setMidiInputDeviceId(const MidiDeviceID& deviceId) override; @@ -45,6 +46,7 @@ class MidiConfigurationStub : public IMidiConfiguration bool useMIDI20Output() const override; void setUseMIDI20Output(bool use) override; + async::Channel useMIDI20OutputChanged() const override; }; } diff --git a/src/framework/stubs/shortcuts/shortcutsconfigurationstub.cpp b/src/framework/stubs/shortcuts/shortcutsconfigurationstub.cpp index 5e6a925d496f9..18e5e2a4abbad 100644 --- a/src/framework/stubs/shortcuts/shortcutsconfigurationstub.cpp +++ b/src/framework/stubs/shortcuts/shortcutsconfigurationstub.cpp @@ -56,3 +56,9 @@ bool ShortcutsConfigurationStub::advanceToNextNoteOnKeyRelease() const void ShortcutsConfigurationStub::setAdvanceToNextNoteOnKeyRelease(bool) { } + +async::Channel ShortcutsConfigurationStub::advanceToNextNoteOnKeyReleaseChanged() const +{ + static async::Channel ch; + return ch; +} diff --git a/src/framework/stubs/shortcuts/shortcutsconfigurationstub.h b/src/framework/stubs/shortcuts/shortcutsconfigurationstub.h index 4265273d000ef..9957b56a33d2a 100644 --- a/src/framework/stubs/shortcuts/shortcutsconfigurationstub.h +++ b/src/framework/stubs/shortcuts/shortcutsconfigurationstub.h @@ -38,6 +38,7 @@ class ShortcutsConfigurationStub : public IShortcutsConfiguration bool advanceToNextNoteOnKeyRelease() const override; void setAdvanceToNextNoteOnKeyRelease(bool value) override; + muse::async::Channel advanceToNextNoteOnKeyReleaseChanged() const override; }; } diff --git a/src/framework/stubs/update/updateconfigurationstub.cpp b/src/framework/stubs/update/updateconfigurationstub.cpp index 9987695b650e2..deea190254af5 100644 --- a/src/framework/stubs/update/updateconfigurationstub.cpp +++ b/src/framework/stubs/update/updateconfigurationstub.cpp @@ -46,6 +46,12 @@ void UpdateConfigurationStub::setNeedCheckForUpdate(bool) { } +muse::async::Notification UpdateConfigurationStub::needCheckForUpdateChanged() const +{ + static muse::async::Notification n; + return n; +} + std::string UpdateConfigurationStub::skippedReleaseVersion() const { return ""; diff --git a/src/framework/stubs/update/updateconfigurationstub.h b/src/framework/stubs/update/updateconfigurationstub.h index 712e15a82db53..86a77ff721bc1 100644 --- a/src/framework/stubs/update/updateconfigurationstub.h +++ b/src/framework/stubs/update/updateconfigurationstub.h @@ -35,6 +35,7 @@ class UpdateConfigurationStub : public IUpdateConfiguration bool needCheckForUpdate() const override; void setNeedCheckForUpdate(bool needCheck) override; + muse::async::Notification needCheckForUpdateChanged() const override; std::string skippedReleaseVersion() const override; void setSkippedReleaseVersion(const std::string& version) override; diff --git a/src/framework/ui/iinteractiveprovider.h b/src/framework/ui/iinteractiveprovider.h index db4f33b6d6424..05d93a6f62945 100644 --- a/src/framework/ui/iinteractiveprovider.h +++ b/src/framework/ui/iinteractiveprovider.h @@ -39,18 +39,20 @@ class IInteractiveProvider : MODULE_EXPORT_INTERFACE virtual ~IInteractiveProvider() = default; virtual RetVal question(const std::string& title, const IInteractive::Text& text, const IInteractive::ButtonDatas& buttons, - int defBtn = int(IInteractive::Button::NoButton), const IInteractive::Options& options = {}) = 0; + int defBtn = int(IInteractive::Button::NoButton), const IInteractive::Options& options = {}, + const std::string& dialogTitle = "") = 0; virtual RetVal info(const std::string& title, const IInteractive::Text& text, const IInteractive::ButtonDatas& buttons, - int defBtn = int(IInteractive::Button::NoButton), const IInteractive::Options& options = {}) = 0; + int defBtn = int(IInteractive::Button::NoButton), const IInteractive::Options& options = {}, + const std::string& dialogTitle = "") = 0; virtual RetVal warning(const std::string& title, const IInteractive::Text& text, const std::string& detailedText = {}, const IInteractive::ButtonDatas& buttons = {}, int defBtn = int(IInteractive::Button::NoButton), - const IInteractive::Options& options = {}) = 0; + const IInteractive::Options& options = {}, const std::string& dialogTitle = "") = 0; virtual RetVal error(const std::string& title, const IInteractive::Text& text, const std::string& detailedText = {}, const IInteractive::ButtonDatas& buttons = {}, int defBtn = int(IInteractive::Button::NoButton), - const IInteractive::Options& options = {}) = 0; + const IInteractive::Options& options = {}, const std::string& dialogTitle = "") = 0; virtual Ret showProgress(const std::string& title, Progress* progress) = 0; diff --git a/src/framework/ui/qml/Muse/Ui/internal/StandardDialog.qml b/src/framework/ui/qml/Muse/Ui/internal/StandardDialog.qml index cdbae3f151aa3..61c5fb935b964 100644 --- a/src/framework/ui/qml/Muse/Ui/internal/StandardDialog.qml +++ b/src/framework/ui/qml/Muse/Ui/internal/StandardDialog.qml @@ -30,6 +30,7 @@ StyledDialogView { property alias type: mainPanel.type + property alias dialogTitle: root.title property alias title: mainPanel.title property alias text: mainPanel.text property alias textFormat: mainPanel.textFormat diff --git a/src/framework/ui/view/interactiveprovider.cpp b/src/framework/ui/view/interactiveprovider.cpp index 7b3c7b76f7cdf..08dbe59f07400 100644 --- a/src/framework/ui/view/interactiveprovider.cpp +++ b/src/framework/ui/view/interactiveprovider.cpp @@ -102,35 +102,39 @@ void InteractiveProvider::raiseWindowInStack(QObject* newActiveWindow) RetVal InteractiveProvider::question(const std::string& title, const IInteractive::Text& text, const IInteractive::ButtonDatas& buttons, int defBtn, - const IInteractive::Options& options) + const IInteractive::Options& options, + const std::string& dialogTitle) { - return openStandardDialog("QUESTION", title, text, {}, buttons, defBtn, options); + return openStandardDialog("QUESTION", title, text, {}, buttons, defBtn, options, dialogTitle); } RetVal InteractiveProvider::info(const std::string& title, const IInteractive::Text& text, const IInteractive::ButtonDatas& buttons, int defBtn, - const IInteractive::Options& options) + const IInteractive::Options& options, + const std::string& dialogTitle) { - return openStandardDialog("INFO", title, text, {}, buttons, defBtn, options); + return openStandardDialog("INFO", title, text, {}, buttons, defBtn, options, dialogTitle); } RetVal InteractiveProvider::warning(const std::string& title, const IInteractive::Text& text, const std::string& detailedText, const IInteractive::ButtonDatas& buttons, int defBtn, - const IInteractive::Options& options) + const IInteractive::Options& options, + const std::string& dialogTitle) { - return openStandardDialog("WARNING", title, text, detailedText, buttons, defBtn, options); + return openStandardDialog("WARNING", title, text, detailedText, buttons, defBtn, options, dialogTitle); } RetVal InteractiveProvider::error(const std::string& title, const IInteractive::Text& text, const std::string& detailedText, const IInteractive::ButtonDatas& buttons, int defBtn, - const IInteractive::Options& options) + const IInteractive::Options& options, + const std::string& dialogTitle) { - return openStandardDialog("ERROR", title, text, detailedText, buttons, defBtn, options); + return openStandardDialog("ERROR", title, text, detailedText, buttons, defBtn, options, dialogTitle); } Ret InteractiveProvider::showProgress(const std::string& title, Progress* progress) @@ -426,7 +430,8 @@ void InteractiveProvider::fillData(QObject* object, const UriQuery& q) const void InteractiveProvider::fillStandardDialogData(QmlLaunchData* data, const QString& type, const std::string& title, const IInteractive::Text& text, const std::string& detailedText, const IInteractive::ButtonDatas& buttons, int defBtn, - const IInteractive::Options& options) const + const IInteractive::Options& options, + const std::string& dialogTitle) const { auto format = [](IInteractive::TextFormat f) { switch (f) { @@ -444,6 +449,7 @@ void InteractiveProvider::fillStandardDialogData(QmlLaunchData* data, const QStr params["detailedText"] = QString::fromStdString(detailedText); params["textFormat"] = format(text.format); params["defaultButtonId"] = defBtn; + params["dialogTitle"] = QString::fromStdString(dialogTitle); QVariantList buttonsList; QVariantList customButtonsList; @@ -720,12 +726,13 @@ RetVal InteractiveProvider::openQml(const UriQuer RetVal InteractiveProvider::openStandardDialog(const QString& type, const std::string& title, const IInteractive::Text& text, const std::string& detailedText, const IInteractive::ButtonDatas& buttons, int defBtn, - const IInteractive::Options& options) + const IInteractive::Options& options, + const std::string& dialogTitle /* the title in the titlebar */) { notifyAboutCurrentUriWillBeChanged(); QmlLaunchData* data = new QmlLaunchData(); - fillStandardDialogData(data, type, title, text, detailedText, buttons, defBtn, options); + fillStandardDialogData(data, type, title, text, detailedText, buttons, defBtn, options, dialogTitle); emit fireOpenStandardDialog(data); diff --git a/src/framework/ui/view/interactiveprovider.h b/src/framework/ui/view/interactiveprovider.h index ee4d3e8c7f8cf..d3e7be2f27faa 100644 --- a/src/framework/ui/view/interactiveprovider.h +++ b/src/framework/ui/view/interactiveprovider.h @@ -62,18 +62,20 @@ class InteractiveProvider : public QObject, public IInteractiveProvider, public explicit InteractiveProvider(const modularity::ContextPtr& iocCtx); RetVal question(const std::string& title, const IInteractive::Text& text, const IInteractive::ButtonDatas& buttons, - int defBtn = int(IInteractive::Button::NoButton), const IInteractive::Options& options = {}) override; + int defBtn = int(IInteractive::Button::NoButton), const IInteractive::Options& options = {}, + const std::string& dialogTitle = "") override; RetVal info(const std::string& title, const IInteractive::Text& text, const IInteractive::ButtonDatas& buttons, - int defBtn = int(IInteractive::Button::NoButton), const IInteractive::Options& options = {}) override; + int defBtn = int(IInteractive::Button::NoButton), const IInteractive::Options& options = {}, + const std::string& dialogTitle = "") override; RetVal warning(const std::string& title, const IInteractive::Text& text, const std::string& detailedText = {}, const IInteractive::ButtonDatas& buttons = {}, int defBtn = int(IInteractive::Button::NoButton), - const IInteractive::Options& options = {}) override; + const IInteractive::Options& options = {}, const std::string& dialogTitle = "") override; RetVal error(const std::string& title, const IInteractive::Text& text, const std::string& detailedText = {}, const IInteractive::ButtonDatas& buttons = {}, int defBtn = int(IInteractive::Button::NoButton), - const IInteractive::Options& options = {}) override; + const IInteractive::Options& options = {}, const std::string& dialogTitle = "") override; Ret showProgress(const std::string& title, Progress* progress) override; @@ -144,7 +146,7 @@ class InteractiveProvider : public QObject, public IInteractiveProvider, public void fillData(QObject* object, const UriQuery& q) const; void fillStandardDialogData(QmlLaunchData* data, const QString& type, const std::string& title, const IInteractive::Text& text, const std::string& detailedText, const IInteractive::ButtonDatas& buttons, int defBtn, - const IInteractive::Options& options) const; + const IInteractive::Options& options, const std::string& dialogTitle) const; void fillFileDialogData(QmlLaunchData* data, FileDialogType type, const std::string& title, const io::path_t& path, const std::vector& filter = {}, bool confirmOverwrite = true) const; @@ -156,7 +158,8 @@ class InteractiveProvider : public QObject, public IInteractiveProvider, public RetVal openQml(const UriQuery& q); RetVal openStandardDialog(const QString& type, const std::string& title, const IInteractive::Text& text, const std::string& detailedText = {}, const IInteractive::ButtonDatas& buttons = {}, - int defBtn = int(IInteractive::Button::NoButton), const IInteractive::Options& options = {}); + int defBtn = int(IInteractive::Button::NoButton), const IInteractive::Options& options = {}, + const std::string& dialogTitle = ""); RetVal openFileDialog(FileDialogType type, const std::string& title, const io::path_t& path, const std::vector& filter = {}, bool confirmOverwrite = true); diff --git a/src/framework/uicomponents/view/buttonboxmodel.h b/src/framework/uicomponents/view/buttonboxmodel.h index 8bca955debe4a..20c51836c656d 100644 --- a/src/framework/uicomponents/view/buttonboxmodel.h +++ b/src/framework/uicomponents/view/buttonboxmodel.h @@ -165,11 +165,11 @@ class ButtonBoxModel : public QObject RejectRole, HelpRole }, // MacLayout - std::vector { CustomRole, HelpRole, ResetRole, RetryRole, DestructiveRole, RejectRole, BackRole, AcceptRole, + std::vector { CustomRole, HelpRole, RetryRole, DestructiveRole, RejectRole, ResetRole, BackRole, AcceptRole, ApplyRole, ContinueRole }, // LinuxLayout - std::vector { CustomRole, HelpRole, ResetRole, RetryRole, DestructiveRole, RejectRole, BackRole, AcceptRole, + std::vector { CustomRole, HelpRole, RetryRole, DestructiveRole, RejectRole, ResetRole, BackRole, AcceptRole, ApplyRole, ContinueRole } }; diff --git a/src/framework/update/internal/updateconfiguration.cpp b/src/framework/update/internal/updateconfiguration.cpp index 96100aaf27d55..4d05376d86210 100644 --- a/src/framework/update/internal/updateconfiguration.cpp +++ b/src/framework/update/internal/updateconfiguration.cpp @@ -64,6 +64,9 @@ void UpdateConfiguration::init() m_config = ConfigReader::read(":/configs/update.cfg"); settings()->setDefaultValue(CHECK_FOR_UPDATE_KEY, Val(isAppUpdatable())); + settings()->valueChanged(CHECK_FOR_UPDATE_KEY).onReceive(this, [this](const Val&) { + m_needCheckForUpdateChanged.notify(); + }); bool allowUpdateOnPreRelease = false; #ifdef MUSESCORE_ALLOW_UPDATE_ON_PRERELEASE @@ -99,6 +102,11 @@ void UpdateConfiguration::setNeedCheckForUpdate(bool needCheck) settings()->setSharedValue(CHECK_FOR_UPDATE_KEY, Val(needCheck)); } +async::Notification UpdateConfiguration::needCheckForUpdateChanged() const +{ + return m_needCheckForUpdateChanged; +} + std::string UpdateConfiguration::skippedReleaseVersion() const { return settings()->value(SKIPPED_VERSION_KEY).toString(); diff --git a/src/framework/update/internal/updateconfiguration.h b/src/framework/update/internal/updateconfiguration.h index ad05f4c8e31f4..35a51639047cf 100644 --- a/src/framework/update/internal/updateconfiguration.h +++ b/src/framework/update/internal/updateconfiguration.h @@ -48,6 +48,7 @@ class UpdateConfiguration : public IUpdateConfiguration, public Injectable, publ bool needCheckForUpdate() const override; void setNeedCheckForUpdate(bool needCheck) override; + muse::async::Notification needCheckForUpdateChanged() const override; std::string skippedReleaseVersion() const override; void setSkippedReleaseVersion(const std::string& version) override; @@ -68,6 +69,7 @@ class UpdateConfiguration : public IUpdateConfiguration, public Injectable, publ muse::io::path_t updateRequestHistoryJsonPath() const override; private: + muse::async::Notification m_needCheckForUpdateChanged; Config m_config; }; diff --git a/src/framework/update/iupdateconfiguration.h b/src/framework/update/iupdateconfiguration.h index 92f8b3f947e77..af23d7b261da5 100644 --- a/src/framework/update/iupdateconfiguration.h +++ b/src/framework/update/iupdateconfiguration.h @@ -22,6 +22,7 @@ #ifndef MUSE_UPDATE_IUPDATECONFIGURATION_H #define MUSE_UPDATE_IUPDATECONFIGURATION_H +#include "async/notification.h" #include "io/path.h" #include "network/networktypes.h" @@ -42,6 +43,7 @@ class IUpdateConfiguration : MODULE_EXPORT_INTERFACE virtual bool needCheckForUpdate() const = 0; virtual void setNeedCheckForUpdate(bool needCheck) = 0; + virtual muse::async::Notification needCheckForUpdateChanged() const = 0; virtual std::string skippedReleaseVersion() const = 0; virtual void setSkippedReleaseVersion(const std::string& version) = 0; diff --git a/src/framework/update/tests/mocks/updateconfigurationmock.h b/src/framework/update/tests/mocks/updateconfigurationmock.h index ce06853a1c13c..b8fa65eee8c56 100644 --- a/src/framework/update/tests/mocks/updateconfigurationmock.h +++ b/src/framework/update/tests/mocks/updateconfigurationmock.h @@ -37,6 +37,7 @@ class UpdateConfigurationMock : public IUpdateConfiguration MOCK_METHOD(bool, needCheckForUpdate, (), (const, override)); MOCK_METHOD(void, setNeedCheckForUpdate, (bool), (override)); + MOCK_METHOD(muse::async::Notification, needCheckForUpdateChanged, (), (const, override)); MOCK_METHOD(std::string, skippedReleaseVersion, (), (const, override)); MOCK_METHOD(void, setSkippedReleaseVersion, (const std::string&), (override)); diff --git a/src/importexport/mei/imeiconfiguration.h b/src/importexport/mei/imeiconfiguration.h index 82b81fa702dde..b110b689887ee 100644 --- a/src/importexport/mei/imeiconfiguration.h +++ b/src/importexport/mei/imeiconfiguration.h @@ -23,6 +23,7 @@ #define MU_IMPORTEXPORT_IMEICONFIGURATION_H #include "modularity/imoduleinterface.h" +#include "async/channel.h" namespace mu::iex::mei { class IMeiConfiguration : MODULE_EXPORT_INTERFACE @@ -34,6 +35,7 @@ class IMeiConfiguration : MODULE_EXPORT_INTERFACE virtual bool meiImportLayout() const = 0; virtual void setMeiImportLayout(bool value) = 0; + virtual muse::async::Channel meiImportLayoutChanged() const = 0; virtual bool meiExportLayout() const = 0; virtual void setMeiExportLayout(bool value) = 0; diff --git a/src/importexport/mei/internal/meiconfiguration.cpp b/src/importexport/mei/internal/meiconfiguration.cpp index f6ec8a7c10a04..94f644a708481 100644 --- a/src/importexport/mei/internal/meiconfiguration.cpp +++ b/src/importexport/mei/internal/meiconfiguration.cpp @@ -35,6 +35,10 @@ static const Settings::Key MEI_EXPORT_LAYOUT_KEY(module_name, "export/mei/export void MeiConfiguration::init() { settings()->setDefaultValue(MEI_IMPORT_LAYOUT_KEY, Val(true)); + settings()->valueChanged(MEI_IMPORT_LAYOUT_KEY).onReceive(this, [this](const Val& val) { + m_meiImportLayoutChanged.send(val.toBool()); + }); + settings()->setDefaultValue(MEI_EXPORT_LAYOUT_KEY, Val(true)); } @@ -48,6 +52,11 @@ void MeiConfiguration::setMeiImportLayout(bool value) settings()->setSharedValue(MEI_IMPORT_LAYOUT_KEY, Val(value)); } +async::Channel MeiConfiguration::meiImportLayoutChanged() const +{ + return m_meiImportLayoutChanged; +} + bool MeiConfiguration::meiExportLayout() const { return settings()->value(MEI_EXPORT_LAYOUT_KEY).toBool(); diff --git a/src/importexport/mei/internal/meiconfiguration.h b/src/importexport/mei/internal/meiconfiguration.h index ecda19989d380..05150fa10d9af 100644 --- a/src/importexport/mei/internal/meiconfiguration.h +++ b/src/importexport/mei/internal/meiconfiguration.h @@ -23,18 +23,23 @@ #define MU_IMPORTEXPORT_MEICONFIGURATION_H #include "../imeiconfiguration.h" +#include "async/asyncable.h" namespace mu::iex::mei { -class MeiConfiguration : public IMeiConfiguration +class MeiConfiguration : public IMeiConfiguration, public muse::async::Asyncable { public: void init(); bool meiImportLayout() const override; void setMeiImportLayout(bool value) override; + muse::async::Channel meiImportLayoutChanged() const override; bool meiExportLayout() const override; void setMeiExportLayout(bool value) override; + +private: + muse::async::Channel m_meiImportLayoutChanged; }; } diff --git a/src/importexport/midi/imidiconfiguration.h b/src/importexport/midi/imidiconfiguration.h index ee1572486baa7..3da00adea8823 100644 --- a/src/importexport/midi/imidiconfiguration.h +++ b/src/importexport/midi/imidiconfiguration.h @@ -25,6 +25,7 @@ #include #include "modularity/imoduleinterface.h" +#include "async/channel.h" #include "io/path.h" namespace mu::iex::midi { @@ -38,6 +39,7 @@ class IMidiImportExportConfiguration : MODULE_EXPORT_INTERFACE // import virtual int midiShortestNote() const = 0; //ticks virtual void setMidiShortestNote(int ticks) = 0; + virtual muse::async::Channel midiShortestNoteChanged() const = 0; virtual void setMidiImportOperationsFile(const std::optional& filePath) const = 0; diff --git a/src/importexport/midi/internal/midiconfiguration.cpp b/src/importexport/midi/internal/midiconfiguration.cpp index 425e2a2ca36ae..28628cdb5b5f5 100644 --- a/src/importexport/midi/internal/midiconfiguration.cpp +++ b/src/importexport/midi/internal/midiconfiguration.cpp @@ -38,6 +38,10 @@ static const Settings::Key EXPAND_REPEATS_KEY("iex_midi", "io/midi/expandRepeats void MidiConfiguration::init() { settings()->setDefaultValue(SHORTEST_NOTE_KEY, Val(mu::engraving::Constants::DIVISION / 4)); + settings()->valueChanged(SHORTEST_NOTE_KEY).onReceive(this, [this](const Val& val) { + m_midiShortestNoteChanged.send(val.toInt()); + }); + settings()->setDefaultValue(EXPAND_REPEATS_KEY, Val(true)); settings()->setDefaultValue(EXPORTRPNS_KEY, Val(true)); } @@ -52,6 +56,11 @@ void MidiConfiguration::setMidiShortestNote(int ticks) settings()->setSharedValue(SHORTEST_NOTE_KEY, Val(ticks)); } +async::Channel MidiConfiguration::midiShortestNoteChanged() const +{ + return m_midiShortestNoteChanged; +} + void MidiConfiguration::setMidiImportOperationsFile(const std::optional& filePath) const { if (filePath) { diff --git a/src/importexport/midi/internal/midiconfiguration.h b/src/importexport/midi/internal/midiconfiguration.h index 5cddbb75b38f3..43b6a0a0d99f6 100644 --- a/src/importexport/midi/internal/midiconfiguration.h +++ b/src/importexport/midi/internal/midiconfiguration.h @@ -22,11 +22,12 @@ #ifndef MU_IMPORTEXPORT_MIDICONFIGURATION_H #define MU_IMPORTEXPORT_MIDICONFIGURATION_H +#include "async/asyncable.h" #include "io/path.h" #include "../imidiconfiguration.h" namespace mu::iex::midi { -class MidiConfiguration : public IMidiImportExportConfiguration +class MidiConfiguration : public IMidiImportExportConfiguration, public muse::async::Asyncable { public: void init(); @@ -34,6 +35,7 @@ class MidiConfiguration : public IMidiImportExportConfiguration // import int midiShortestNote() const override; // ticks void setMidiShortestNote(int ticks) override; + muse::async::Channel midiShortestNoteChanged() const override; void setMidiImportOperationsFile(const std::optional& filePath) const override; @@ -43,6 +45,9 @@ class MidiConfiguration : public IMidiImportExportConfiguration bool isMidiExportRpns() const override; void setIsMidiExportRpns(bool exportRpns) override; + +private: + muse::async::Channel m_midiShortestNoteChanged; }; } diff --git a/src/importexport/musicxml/imusicxmlconfiguration.h b/src/importexport/musicxml/imusicxmlconfiguration.h index 048a6f3f08d67..8096ac0e48552 100644 --- a/src/importexport/musicxml/imusicxmlconfiguration.h +++ b/src/importexport/musicxml/imusicxmlconfiguration.h @@ -22,6 +22,7 @@ #pragma once #include "modularity/imoduleinterface.h" +#include "async/channel.h" #include "io/path.h" namespace mu::iex::musicxml { @@ -34,9 +35,11 @@ class IMusicXmlConfiguration : MODULE_EXPORT_INTERFACE virtual bool importBreaks() const = 0; virtual void setImportBreaks(bool value) = 0; + virtual muse::async::Channel importBreaksChanged() const = 0; virtual bool importLayout() const = 0; virtual void setImportLayout(bool value) = 0; + virtual muse::async::Channel importLayoutChanged() const = 0; virtual bool exportLayout() const = 0; virtual void setExportLayout(bool value) = 0; @@ -56,13 +59,16 @@ class IMusicXmlConfiguration : MODULE_EXPORT_INTERFACE virtual bool needUseDefaultFont() const = 0; virtual void setNeedUseDefaultFont(bool value) = 0; + virtual muse::async::Channel needUseDefaultFontChanged() const = 0; virtual void setNeedUseDefaultFontOverride(std::optional value) = 0; virtual bool needAskAboutApplyingNewStyle() const = 0; virtual void setNeedAskAboutApplyingNewStyle(bool value) = 0; + virtual muse::async::Channel needAskAboutApplyingNewStyleChanged() const = 0; virtual bool inferTextType() const = 0; virtual void setInferTextType(bool value) = 0; + virtual muse::async::Channel inferTextTypeChanged() const = 0; virtual void setInferTextTypeOverride(std::optional value) = 0; }; } diff --git a/src/importexport/musicxml/internal/musicxmlconfiguration.cpp b/src/importexport/musicxml/internal/musicxmlconfiguration.cpp index 06797ad015505..2c112692d1faf 100644 --- a/src/importexport/musicxml/internal/musicxmlconfiguration.cpp +++ b/src/importexport/musicxml/internal/musicxmlconfiguration.cpp @@ -43,7 +43,15 @@ static const Settings::Key MUSICXML_IMPORT_INFER_TEXT_TYPE(module_name, "import/ void MusicXmlConfiguration::init() { settings()->setDefaultValue(MUSICXML_IMPORT_BREAKS_KEY, Val(true)); + settings()->valueChanged(MUSICXML_IMPORT_BREAKS_KEY).onReceive(this, [this](const Val& val) { + m_importBreaksChanged.send(val.toBool()); + }); + settings()->setDefaultValue(MUSICXML_IMPORT_LAYOUT_KEY, Val(true)); + settings()->valueChanged(MUSICXML_IMPORT_LAYOUT_KEY).onReceive(this, [this](const Val& val) { + m_importLayoutChanged.send(val.toBool()); + }); + settings()->setDefaultValue(MUSICXML_EXPORT_LAYOUT_KEY, Val(true)); settings()->setDefaultValue(MUSICXML_EXPORT_MU3_COMPAT_KEY, Val(false)); settings()->setDescription(MUSICXML_EXPORT_MU3_COMPAT_KEY, @@ -56,9 +64,21 @@ void MusicXmlConfiguration::init() settings()->setDescription(MUSICXML_EXPORT_INVISIBLE_ELEMENTS_KEY, muse::trc("iex_musicxml", "Export invisible elements to MusicXML")); settings()->setCanBeManuallyEdited(MUSICXML_EXPORT_INVISIBLE_ELEMENTS_KEY, true); + settings()->setDefaultValue(MIGRATION_APPLY_EDWIN_FOR_XML, Val(false)); + settings()->valueChanged(MIGRATION_APPLY_EDWIN_FOR_XML).onReceive(this, [this](const Val& val) { + m_needUseDefaultFontChanged.send(val.toBool()); + }); + settings()->setDefaultValue(MIGRATION_NOT_ASK_AGAIN_KEY, Val(false)); + settings()->valueChanged(MIGRATION_NOT_ASK_AGAIN_KEY).onReceive(this, [this](const Val& val) { + m_needAskAboutApplyingNewStyleChanged.send(val.toBool()); + }); + settings()->setDefaultValue(MUSICXML_IMPORT_INFER_TEXT_TYPE, Val(false)); + settings()->valueChanged(MUSICXML_IMPORT_INFER_TEXT_TYPE).onReceive(this, [this](const Val& val) { + m_inferTextTypeChanged.send(val.toBool()); + }); } bool MusicXmlConfiguration::importBreaks() const @@ -71,6 +91,11 @@ void MusicXmlConfiguration::setImportBreaks(bool value) settings()->setSharedValue(MUSICXML_IMPORT_BREAKS_KEY, Val(value)); } +async::Channel MusicXmlConfiguration::importBreaksChanged() const +{ + return m_importBreaksChanged; +} + bool MusicXmlConfiguration::importLayout() const { return settings()->value(MUSICXML_IMPORT_LAYOUT_KEY).toBool(); @@ -81,6 +106,11 @@ void MusicXmlConfiguration::setImportLayout(bool value) settings()->setSharedValue(MUSICXML_IMPORT_LAYOUT_KEY, Val(value)); } +async::Channel MusicXmlConfiguration::importLayoutChanged() const +{ + return m_importLayoutChanged; +} + bool MusicXmlConfiguration::exportLayout() const { return settings()->value(MUSICXML_EXPORT_LAYOUT_KEY).toBool(); @@ -135,6 +165,11 @@ void MusicXmlConfiguration::setNeedUseDefaultFont(bool value) settings()->setSharedValue(MIGRATION_APPLY_EDWIN_FOR_XML, Val(value)); } +async::Channel MusicXmlConfiguration::needUseDefaultFontChanged() const +{ + return m_needUseDefaultFontChanged; +} + void MusicXmlConfiguration::setNeedUseDefaultFontOverride(std::optional value) { m_needUseDefaultFontOverride = value; @@ -150,6 +185,11 @@ void MusicXmlConfiguration::setNeedAskAboutApplyingNewStyle(bool value) settings()->setSharedValue(MIGRATION_NOT_ASK_AGAIN_KEY, Val(!value)); } +async::Channel MusicXmlConfiguration::needAskAboutApplyingNewStyleChanged() const +{ + return m_needAskAboutApplyingNewStyleChanged; +} + bool MusicXmlConfiguration::inferTextType() const { if (m_inferTextTypeOverride.has_value()) { @@ -164,6 +204,11 @@ void MusicXmlConfiguration::setInferTextType(bool value) settings()->setSharedValue(MUSICXML_IMPORT_INFER_TEXT_TYPE, Val(value)); } +async::Channel MusicXmlConfiguration::inferTextTypeChanged() const +{ + return m_inferTextTypeChanged; +} + void MusicXmlConfiguration::setInferTextTypeOverride(std::optional value) { m_inferTextTypeOverride = value; diff --git a/src/importexport/musicxml/internal/musicxmlconfiguration.h b/src/importexport/musicxml/internal/musicxmlconfiguration.h index 67b976e8a2fc9..3ddc414ace175 100644 --- a/src/importexport/musicxml/internal/musicxmlconfiguration.h +++ b/src/importexport/musicxml/internal/musicxmlconfiguration.h @@ -22,18 +22,21 @@ #pragma once #include "../imusicxmlconfiguration.h" +#include "async/asyncable.h" namespace mu::iex::musicxml { -class MusicXmlConfiguration : public IMusicXmlConfiguration +class MusicXmlConfiguration : public IMusicXmlConfiguration, public muse::async::Asyncable { public: void init(); bool importBreaks() const override; void setImportBreaks(bool value) override; + muse::async::Channel importBreaksChanged() const override; bool importLayout() const override; void setImportLayout(bool value) override; + muse::async::Channel importLayoutChanged() const override; bool exportLayout() const override; void setExportLayout(bool value) override; @@ -49,17 +52,26 @@ class MusicXmlConfiguration : public IMusicXmlConfiguration bool needUseDefaultFont() const override; void setNeedUseDefaultFont(bool value) override; + muse::async::Channel needUseDefaultFontChanged() const override; void setNeedUseDefaultFontOverride(std::optional value) override; bool needAskAboutApplyingNewStyle() const override; void setNeedAskAboutApplyingNewStyle(bool value) override; + muse::async::Channel needAskAboutApplyingNewStyleChanged() const override; bool inferTextType() const override; void setInferTextType(bool value) override; + muse::async::Channel inferTextTypeChanged() const override; void setInferTextTypeOverride(std::optional value) override; private: std::optional m_needUseDefaultFontOverride; std::optional m_inferTextTypeOverride; + + muse::async::Channel m_importBreaksChanged; + muse::async::Channel m_importLayoutChanged; + muse::async::Channel m_needUseDefaultFontChanged; + muse::async::Channel m_needAskAboutApplyingNewStyleChanged; + muse::async::Channel m_inferTextTypeChanged; }; } diff --git a/src/importexport/ove/internal/oveconfiguration.cpp b/src/importexport/ove/internal/oveconfiguration.cpp index 29049fa3db90e..cef89e99fb7a3 100644 --- a/src/importexport/ove/internal/oveconfiguration.cpp +++ b/src/importexport/ove/internal/oveconfiguration.cpp @@ -32,6 +32,9 @@ static const Settings::Key IMPORT_OVERTURE_CHARSET_KEY("iex_ove", "import/overtu void OveConfiguration::init() { settings()->setDefaultValue(IMPORT_OVERTURE_CHARSET_KEY, Val("GBK")); + settings()->valueChanged(IMPORT_OVERTURE_CHARSET_KEY).onReceive(this, [this](const Val& val) { + m_importOvertureCharsetChanged.send(val.toString()); + }); } std::string OveConfiguration::importOvertureCharset() const @@ -43,3 +46,8 @@ void OveConfiguration::setImportOvertureCharset(const std::string& charset) { settings()->setSharedValue(IMPORT_OVERTURE_CHARSET_KEY, Val(charset)); } + +async::Channel OveConfiguration::importOvertureCharsetChanged() const +{ + return m_importOvertureCharsetChanged; +} diff --git a/src/importexport/ove/internal/oveconfiguration.h b/src/importexport/ove/internal/oveconfiguration.h index 178dbbec0b658..e580bfb88af51 100644 --- a/src/importexport/ove/internal/oveconfiguration.h +++ b/src/importexport/ove/internal/oveconfiguration.h @@ -23,15 +23,20 @@ #define MU_IMPORTEXPORT_OVECONFIGURATION_H #include "../ioveconfiguration.h" +#include "async/asyncable.h" namespace mu::iex::ove { -class OveConfiguration : public IOveConfiguration +class OveConfiguration : public IOveConfiguration, public muse::async::Asyncable { public: void init(); std::string importOvertureCharset() const override; void setImportOvertureCharset(const std::string& charset) override; + muse::async::Channel importOvertureCharsetChanged() const override; + +private: + muse::async::Channel m_importOvertureCharsetChanged; }; } diff --git a/src/importexport/ove/ioveconfiguration.h b/src/importexport/ove/ioveconfiguration.h index 8dc6cb795da46..cc06f254d1d75 100644 --- a/src/importexport/ove/ioveconfiguration.h +++ b/src/importexport/ove/ioveconfiguration.h @@ -24,6 +24,7 @@ #include +#include "async/channel.h" #include "modularity/imoduleinterface.h" namespace mu::iex::ove { @@ -36,6 +37,7 @@ class IOveConfiguration : MODULE_EXPORT_INTERFACE virtual std::string importOvertureCharset() const = 0; virtual void setImportOvertureCharset(const std::string& charset) = 0; + virtual muse::async::Channel importOvertureCharsetChanged() const = 0; }; } diff --git a/src/notation/inotationconfiguration.h b/src/notation/inotationconfiguration.h index 6c7744271e39d..3e26774103abd 100644 --- a/src/notation/inotationconfiguration.h +++ b/src/notation/inotationconfiguration.h @@ -83,12 +83,14 @@ class INotationConfiguration : MODULE_EXPORT_INTERFACE virtual int selectionProximity() const = 0; virtual void setSelectionProximity(int proximity) = 0; + virtual muse::async::Channel selectionProximityChanged() const = 0; virtual ZoomType defaultZoomType() const = 0; virtual void setDefaultZoomType(ZoomType zoomType) = 0; virtual int defaultZoom() const = 0; virtual void setDefaultZoom(int zoomPercentage) = 0; + virtual muse::async::Notification defaultZoomChanged() const = 0; virtual QList possibleZoomPercentageList() const = 0; @@ -97,6 +99,7 @@ class INotationConfiguration : MODULE_EXPORT_INTERFACE virtual int mouseZoomPrecision() const = 0; virtual void setMouseZoomPrecision(int precision) = 0; + virtual muse::async::Notification mouseZoomPrecisionChanged() const = 0; virtual std::string fontFamily() const = 0; virtual int fontSize() const = 0; @@ -107,9 +110,11 @@ class INotationConfiguration : MODULE_EXPORT_INTERFACE virtual muse::io::path_t defaultStyleFilePath() const = 0; virtual void setDefaultStyleFilePath(const muse::io::path_t& path) = 0; + virtual muse::async::Channel defaultStyleFilePathChanged() const = 0; virtual muse::io::path_t partStyleFilePath() const = 0; virtual void setPartStyleFilePath(const muse::io::path_t& path) = 0; + virtual muse::async::Channel partStyleFilePathChanged() const = 0; virtual bool isMidiInputEnabled() const = 0; virtual void setIsMidiInputEnabled(bool enabled) = 0; @@ -146,15 +151,19 @@ class INotationConfiguration : MODULE_EXPORT_INTERFACE virtual bool colorNotesOutsideOfUsablePitchRange() const = 0; virtual void setColorNotesOutsideOfUsablePitchRange(bool value) = 0; + virtual muse::async::Channel colorNotesOutsideOfUsablePitchRangeChanged() const = 0; virtual bool warnGuitarBends() const = 0; virtual void setWarnGuitarBends(bool value) = 0; + virtual muse::async::Channel warnGuitarBendsChanged() const = 0; virtual int delayBetweenNotesInRealTimeModeMilliseconds() const = 0; virtual void setDelayBetweenNotesInRealTimeModeMilliseconds(int delayMs) = 0; + virtual muse::async::Channel delayBetweenNotesInRealTimeModeMillisecondsChanged() const = 0; virtual int notePlayDurationMilliseconds() const = 0; virtual void setNotePlayDurationMilliseconds(int durationMs) = 0; + virtual muse::async::Channel notePlayDurationMillisecondsChanged() const = 0; virtual void setTemplateModeEnabled(std::optional enabled) = 0; virtual void setTestModeEnabled(std::optional enabled) = 0; @@ -211,6 +220,7 @@ class INotationConfiguration : MODULE_EXPORT_INTERFACE virtual muse::io::path_t styleFileImportPath() const = 0; virtual void setStyleFileImportPath(const muse::io::path_t& path) = 0; + virtual muse::async::Channel styleFileImportPathChanged() const = 0; virtual int styleDialogLastPageIndex() const = 0; virtual void setStyleDialogLastPageIndex(int value) = 0; diff --git a/src/notation/internal/notationconfiguration.cpp b/src/notation/internal/notationconfiguration.cpp index 64cce14817e69..1398ab7b73c03 100644 --- a/src/notation/internal/notationconfiguration.cpp +++ b/src/notation/internal/notationconfiguration.cpp @@ -153,9 +153,18 @@ void NotationConfiguration::init() }); settings()->setDefaultValue(DEFAULT_ZOOM_TYPE, Val(ZoomType::Percentage)); + settings()->valueChanged(DEFAULT_ZOOM_TYPE).onReceive(this, [this](const Val&) { + m_defaultZoomChanged.notify(); + }); settings()->setDefaultValue(DEFAULT_ZOOM, Val(100)); + settings()->valueChanged(DEFAULT_ZOOM).onReceive(this, [this](const Val&) { + m_defaultZoomChanged.notify(); + }); settings()->setDefaultValue(KEYBOARD_ZOOM_PRECISION, Val(2)); settings()->setDefaultValue(MOUSE_ZOOM_PRECISION, Val(6)); + settings()->valueChanged(MOUSE_ZOOM_PRECISION).onReceive(this, [this](const Val&) { + m_mouseZoomPrecisionChanged.notify(); + }); settings()->setDefaultValue(USER_STYLES_PATH, Val(globalConfiguration()->userDataPath() + "/Styles")); settings()->valueChanged(USER_STYLES_PATH).onReceive(nullptr, [this](const Val& val) { @@ -167,6 +176,9 @@ void NotationConfiguration::init() } settings()->setDefaultValue(SELECTION_PROXIMITY, Val(2)); + settings()->valueChanged(SELECTION_PROXIMITY).onReceive(this, [this](const Val& val) { + m_selectionProximityChanged.send(val.toInt()); + }); settings()->setDefaultValue(IS_MIDI_INPUT_ENABLED, Val(true)); settings()->setDefaultValue(IS_AUTOMATICALLY_PAN_ENABLED, Val(true)); settings()->setDefaultValue(IS_PLAY_REPEATS_ENABLED, Val(true)); @@ -193,9 +205,26 @@ void NotationConfiguration::init() }); settings()->setDefaultValue(COLOR_NOTES_OUTSIDE_OF_USABLE_PITCH_RANGE, Val(true)); + settings()->valueChanged(COLOR_NOTES_OUTSIDE_OF_USABLE_PITCH_RANGE).onReceive(this, [this](const Val& val) { + m_colorNotesOutsideOfUsablePitchRangeChanged.send(val.toBool()); + }); settings()->setDefaultValue(WARN_GUITAR_BENDS, Val(true)); + settings()->valueChanged(WARN_GUITAR_BENDS).onReceive(this, [this](const Val& val) { + m_warnGuitarBendsChanged.send(val.toBool()); + }); settings()->setDefaultValue(REALTIME_DELAY, Val(750)); + settings()->valueChanged(REALTIME_DELAY).onReceive(this, [this](const Val& val) { + m_delayBetweenNotesInRealTimeModeMillisecondsChanged.send(val.toInt()); + }); settings()->setDefaultValue(NOTE_DEFAULT_PLAY_DURATION, Val(500)); + settings()->valueChanged(NOTE_DEFAULT_PLAY_DURATION).onReceive(this, [this](const Val& val) { + m_notePlayDurationMillisecondsChanged.send(val.toInt()); + }); + + settings()->setDefaultValue(STYLE_FILE_IMPORT_PATH_KEY, Val("")); + settings()->valueChanged(STYLE_FILE_IMPORT_PATH_KEY).onReceive(this, [this](const Val& val) { + m_styleFileImportPathChanged.send(val.toString()); + }); settings()->setDefaultValue(FIRST_SCORE_ORDER_LIST_KEY, Val(globalConfiguration()->appDataPath().toStdString() + "instruments/orders.xml")); @@ -480,6 +509,11 @@ void NotationConfiguration::setSelectionProximity(int proximity) settings()->setSharedValue(SELECTION_PROXIMITY, Val(proximity)); } +Channel NotationConfiguration::selectionProximityChanged() const +{ + return m_selectionProximityChanged; +} + ZoomType NotationConfiguration::defaultZoomType() const { return settings()->value(DEFAULT_ZOOM_TYPE).toEnum(); @@ -500,6 +534,11 @@ void NotationConfiguration::setDefaultZoom(int zoomPercentage) settings()->setSharedValue(DEFAULT_ZOOM, Val(zoomPercentage)); } +Notification NotationConfiguration::defaultZoomChanged() const +{ + return m_defaultZoomChanged; +} + qreal NotationConfiguration::scalingFromZoomPercentage(int zoomPercentage) const { return zoomPercentage / 100.0 * notationScaling(); @@ -527,6 +566,11 @@ void NotationConfiguration::setMouseZoomPrecision(int precision) settings()->setSharedValue(MOUSE_ZOOM_PRECISION, Val(precision)); } +Notification NotationConfiguration::mouseZoomPrecisionChanged() const +{ + return m_mouseZoomPrecisionChanged; +} + std::string NotationConfiguration::fontFamily() const { return uiConfiguration()->fontFamily(); @@ -562,6 +606,11 @@ void NotationConfiguration::setDefaultStyleFilePath(const muse::io::path_t& path engravingConfiguration()->setDefaultStyleFilePath(path.toQString()); } +async::Channel NotationConfiguration::defaultStyleFilePathChanged() const +{ + return engravingConfiguration()->defaultStyleFilePathChanged(); +} + muse::io::path_t NotationConfiguration::partStyleFilePath() const { return engravingConfiguration()->partStyleFilePath(); @@ -572,6 +621,11 @@ void NotationConfiguration::setPartStyleFilePath(const muse::io::path_t& path) engravingConfiguration()->setPartStyleFilePath(path.toQString()); } +async::Channel NotationConfiguration::partStyleFilePathChanged() const +{ + return engravingConfiguration()->partStyleFilePathChanged(); +} + bool NotationConfiguration::isMidiInputEnabled() const { return settings()->value(IS_MIDI_INPUT_ENABLED).toBool(); @@ -707,6 +761,11 @@ void NotationConfiguration::setColorNotesOutsideOfUsablePitchRange(bool value) settings()->setSharedValue(COLOR_NOTES_OUTSIDE_OF_USABLE_PITCH_RANGE, Val(value)); } +async::Channel NotationConfiguration::colorNotesOutsideOfUsablePitchRangeChanged() const +{ + return m_colorNotesOutsideOfUsablePitchRangeChanged; +} + bool NotationConfiguration::warnGuitarBends() const { return settings()->value(WARN_GUITAR_BENDS).toBool(); @@ -718,6 +777,11 @@ void NotationConfiguration::setWarnGuitarBends(bool value) settings()->setSharedValue(WARN_GUITAR_BENDS, Val(value)); } +async::Channel NotationConfiguration::warnGuitarBendsChanged() const +{ + return m_warnGuitarBendsChanged; +} + int NotationConfiguration::delayBetweenNotesInRealTimeModeMilliseconds() const { return settings()->value(REALTIME_DELAY).toInt(); @@ -728,6 +792,11 @@ void NotationConfiguration::setDelayBetweenNotesInRealTimeModeMilliseconds(int d settings()->setSharedValue(REALTIME_DELAY, Val(delayMs)); } +async::Channel NotationConfiguration::delayBetweenNotesInRealTimeModeMillisecondsChanged() const +{ + return m_delayBetweenNotesInRealTimeModeMillisecondsChanged; +} + int NotationConfiguration::notePlayDurationMilliseconds() const { return settings()->value(NOTE_DEFAULT_PLAY_DURATION).toInt(); @@ -739,6 +808,11 @@ void NotationConfiguration::setNotePlayDurationMilliseconds(int durationMs) settings()->setSharedValue(NOTE_DEFAULT_PLAY_DURATION, Val(durationMs)); } +async::Channel NotationConfiguration::notePlayDurationMillisecondsChanged() const +{ + return m_notePlayDurationMillisecondsChanged; +} + void NotationConfiguration::setTemplateModeEnabled(std::optional enabled) { mu::engraving::MScore::saveTemplateMode = enabled ? enabled.value() : false; @@ -1002,6 +1076,11 @@ void NotationConfiguration::setStyleFileImportPath(const muse::io::path_t& path) settings()->setSharedValue(STYLE_FILE_IMPORT_PATH_KEY, Val(path.toStdString())); } +async::Channel NotationConfiguration::styleFileImportPathChanged() const +{ + return m_styleFileImportPathChanged; +} + int NotationConfiguration::styleDialogLastPageIndex() const { return m_styleDialogLastPageIndex; diff --git a/src/notation/internal/notationconfiguration.h b/src/notation/internal/notationconfiguration.h index a24da7e3a5687..1bb7a71ac2585 100644 --- a/src/notation/internal/notationconfiguration.h +++ b/src/notation/internal/notationconfiguration.h @@ -88,12 +88,14 @@ class NotationConfiguration : public INotationConfiguration, public muse::async: int selectionProximity() const override; void setSelectionProximity(int proximity) override; + muse::async::Channel selectionProximityChanged() const override; ZoomType defaultZoomType() const override; void setDefaultZoomType(ZoomType zoomType) override; int defaultZoom() const override; void setDefaultZoom(int zoomPercentage) override; + muse::async::Notification defaultZoomChanged() const override; qreal scalingFromZoomPercentage(int zoomPercentage) const override; int zoomPercentageFromScaling(qreal scaling) const override; @@ -102,6 +104,7 @@ class NotationConfiguration : public INotationConfiguration, public muse::async: int mouseZoomPrecision() const override; void setMouseZoomPrecision(int precision) override; + muse::async::Notification mouseZoomPrecisionChanged() const override; std::string fontFamily() const override; int fontSize() const override; @@ -112,9 +115,11 @@ class NotationConfiguration : public INotationConfiguration, public muse::async: muse::io::path_t defaultStyleFilePath() const override; void setDefaultStyleFilePath(const muse::io::path_t& path) override; + muse::async::Channel defaultStyleFilePathChanged() const override; muse::io::path_t partStyleFilePath() const override; void setPartStyleFilePath(const muse::io::path_t& path) override; + muse::async::Channel partStyleFilePathChanged() const override; bool isMidiInputEnabled() const override; void setIsMidiInputEnabled(bool enabled) override; @@ -151,15 +156,19 @@ class NotationConfiguration : public INotationConfiguration, public muse::async: bool colorNotesOutsideOfUsablePitchRange() const override; void setColorNotesOutsideOfUsablePitchRange(bool value) override; + muse::async::Channel colorNotesOutsideOfUsablePitchRangeChanged() const override; bool warnGuitarBends() const override; void setWarnGuitarBends(bool value) override; + muse::async::Channel warnGuitarBendsChanged() const override; int delayBetweenNotesInRealTimeModeMilliseconds() const override; void setDelayBetweenNotesInRealTimeModeMilliseconds(int delayMs) override; + muse::async::Channel delayBetweenNotesInRealTimeModeMillisecondsChanged() const override; int notePlayDurationMilliseconds() const override; void setNotePlayDurationMilliseconds(int durationMs) override; + muse::async::Channel notePlayDurationMillisecondsChanged() const override; void setTemplateModeEnabled(std::optional enabled) override; void setTestModeEnabled(std::optional enabled) override; @@ -216,6 +225,7 @@ class NotationConfiguration : public INotationConfiguration, public muse::async: muse::io::path_t styleFileImportPath() const override; void setStyleFileImportPath(const muse::io::path_t& path) override; + muse::async::Channel styleFileImportPathChanged() const override; int styleDialogLastPageIndex() const override; void setStyleDialogLastPageIndex(int value) override; @@ -235,10 +245,18 @@ class NotationConfiguration : public INotationConfiguration, public muse::async: muse::async::Notification m_backgroundChanged; muse::async::Notification m_foregroundChanged; + muse::async::Notification m_defaultZoomChanged; + muse::async::Notification m_mouseZoomPrecisionChanged; muse::async::Channel m_canvasOrientationChanged; muse::async::Channel m_userStylesPathChanged; muse::async::Notification m_scoreOrderListPathsChanged; muse::async::Notification m_isLimitCanvasScrollAreaChanged; + muse::async::Channel m_selectionProximityChanged; + muse::async::Channel m_colorNotesOutsideOfUsablePitchRangeChanged; + muse::async::Channel m_warnGuitarBendsChanged; + muse::async::Channel m_delayBetweenNotesInRealTimeModeMillisecondsChanged; + muse::async::Channel m_notePlayDurationMillisecondsChanged; + muse::async::Channel m_styleFileImportPathChanged; muse::async::Notification m_isPlayRepeatsChanged; muse::async::Notification m_isPlayChordSymbolsChanged; muse::ValCh m_pianoKeyboardNumberOfKeys; diff --git a/src/notation/tests/mocks/notationconfigurationmock.h b/src/notation/tests/mocks/notationconfigurationmock.h index a0c553e54d283..d2b93f81789f3 100644 --- a/src/notation/tests/mocks/notationconfigurationmock.h +++ b/src/notation/tests/mocks/notationconfigurationmock.h @@ -73,12 +73,14 @@ class NotationConfigurationMock : public INotationConfiguration MOCK_METHOD(int, selectionProximity, (), (const, override)); MOCK_METHOD(void, setSelectionProximity, (int), (override)); + MOCK_METHOD(muse::async::Channel, selectionProximityChanged, (), (const, override)); MOCK_METHOD(ZoomType, defaultZoomType, (), (const, override)); MOCK_METHOD(void, setDefaultZoomType, (ZoomType), (override)); MOCK_METHOD(int, defaultZoom, (), (const, override)); MOCK_METHOD(void, setDefaultZoom, (int), (override)); + MOCK_METHOD(muse::async::Notification, defaultZoomChanged, (), (const, override)); MOCK_METHOD(QList, possibleZoomPercentageList, (), (const, override)); @@ -87,6 +89,7 @@ class NotationConfigurationMock : public INotationConfiguration MOCK_METHOD(int, mouseZoomPrecision, (), (const, override)); MOCK_METHOD(void, setMouseZoomPrecision, (int), (override)); + MOCK_METHOD(muse::async::Notification, mouseZoomPrecisionChanged, (), (const, override)); MOCK_METHOD(std::string, fontFamily, (), (const, override)); MOCK_METHOD(int, fontSize, (), (const, override)); @@ -97,9 +100,11 @@ class NotationConfigurationMock : public INotationConfiguration MOCK_METHOD(muse::io::path_t, defaultStyleFilePath, (), (const, override)); MOCK_METHOD(void, setDefaultStyleFilePath, (const muse::io::path_t&), (override)); + MOCK_METHOD(muse::async::Channel, defaultStyleFilePathChanged, (), (const, override)); MOCK_METHOD(muse::io::path_t, partStyleFilePath, (), (const, override)); MOCK_METHOD(void, setPartStyleFilePath, (const muse::io::path_t&), (override)); + MOCK_METHOD(muse::async::Channel, partStyleFilePathChanged, (), (const, override)); MOCK_METHOD(bool, isMidiInputEnabled, (), (const, override)); MOCK_METHOD(void, setIsMidiInputEnabled, (bool), (override)); @@ -136,15 +141,19 @@ class NotationConfigurationMock : public INotationConfiguration MOCK_METHOD(bool, colorNotesOutsideOfUsablePitchRange, (), (const, override)); MOCK_METHOD(void, setColorNotesOutsideOfUsablePitchRange, (bool), (override)); + MOCK_METHOD((muse::async::Channel), colorNotesOutsideOfUsablePitchRangeChanged, (), (const, override)); MOCK_METHOD(bool, warnGuitarBends, (), (const, override)); MOCK_METHOD(void, setWarnGuitarBends, (bool), (override)); + MOCK_METHOD((muse::async::Channel), warnGuitarBendsChanged, (), (const, override)); MOCK_METHOD(int, delayBetweenNotesInRealTimeModeMilliseconds, (), (const, override)); MOCK_METHOD(void, setDelayBetweenNotesInRealTimeModeMilliseconds, (int), (override)); + MOCK_METHOD((muse::async::Channel), delayBetweenNotesInRealTimeModeMillisecondsChanged, (), (const, override)); MOCK_METHOD(int, notePlayDurationMilliseconds, (), (const, override)); MOCK_METHOD(void, setNotePlayDurationMilliseconds, (int), (override)); + MOCK_METHOD((muse::async::Channel), notePlayDurationMillisecondsChanged, (), (const, override)); MOCK_METHOD(void, setTemplateModeEnabled, (std::optional), (override)); MOCK_METHOD(void, setTestModeEnabled, (std::optional), (override)); @@ -201,6 +210,7 @@ class NotationConfigurationMock : public INotationConfiguration MOCK_METHOD(muse::io::path_t, styleFileImportPath, (), (const, override)); MOCK_METHOD(void, setStyleFileImportPath, (const muse::io::path_t&), (override)); + MOCK_METHOD((muse::async::Channel), styleFileImportPathChanged, (), (const, override)); MOCK_METHOD(int, styleDialogLastPageIndex, (), (const, override)); MOCK_METHOD(void, setStyleDialogLastPageIndex, (int), (override)); diff --git a/src/playback/internal/playbackconfiguration.cpp b/src/playback/internal/playbackconfiguration.cpp index de71d24597a27..4932da6a6a87c 100644 --- a/src/playback/internal/playbackconfiguration.cpp +++ b/src/playback/internal/playbackconfiguration.cpp @@ -96,7 +96,13 @@ void PlaybackConfiguration::init() m_playNotesWhenEditingChanged.notify(); }); settings()->setDefaultValue(PLAY_CHORD_WHEN_EDITING, Val(true)); + settings()->valueChanged(PLAY_CHORD_WHEN_EDITING).onReceive(this, [this](const Val& val) { + m_playChordWhenEditingChanged.send(val.toBool()); + }); settings()->setDefaultValue(PLAY_HARMONY_WHEN_EDITING, Val(true)); + settings()->valueChanged(PLAY_HARMONY_WHEN_EDITING).onReceive(this, [this](const Val& val) { + m_playHarmonyWhenEditingChanged.send(val.toBool()); + }); settings()->setDefaultValue(PLAYBACK_CURSOR_TYPE_KEY, Val(PlaybackCursorType::STEPPED)); settings()->setDefaultValue(SOUND_PRESETS_MULTI_SELECTION_KEY, Val(false)); settings()->setDefaultValue(MIXER_RESET_SOUND_FLAGS_WHEN_CHANGE_SOUND_WARNING, Val(true)); @@ -159,6 +165,11 @@ void PlaybackConfiguration::setPlayChordWhenEditing(bool value) settings()->setSharedValue(PLAY_CHORD_WHEN_EDITING, Val(value)); } +async::Channel PlaybackConfiguration::playChordWhenEditingChanged() const +{ + return m_playChordWhenEditingChanged; +} + bool PlaybackConfiguration::playHarmonyWhenEditing() const { return settings()->value(PLAY_HARMONY_WHEN_EDITING).toBool(); @@ -169,6 +180,11 @@ void PlaybackConfiguration::setPlayHarmonyWhenEditing(bool value) settings()->setSharedValue(PLAY_HARMONY_WHEN_EDITING, Val(value)); } +async::Channel PlaybackConfiguration::playHarmonyWhenEditingChanged() const +{ + return m_playHarmonyWhenEditingChanged; +} + PlaybackCursorType PlaybackConfiguration::cursorType() const { return settings()->value(PLAYBACK_CURSOR_TYPE_KEY).toEnum(); diff --git a/src/playback/internal/playbackconfiguration.h b/src/playback/internal/playbackconfiguration.h index 4115718dbafb0..1c13bcc328afb 100644 --- a/src/playback/internal/playbackconfiguration.h +++ b/src/playback/internal/playbackconfiguration.h @@ -44,9 +44,11 @@ class PlaybackConfiguration : public IPlaybackConfiguration, public muse::async: bool playChordWhenEditing() const override; void setPlayChordWhenEditing(bool value) override; + muse::async::Channel playChordWhenEditingChanged() const override; bool playHarmonyWhenEditing() const override; void setPlayHarmonyWhenEditing(bool value) override; + muse::async::Channel playHarmonyWhenEditingChanged() const override; PlaybackCursorType cursorType() const override; @@ -89,7 +91,8 @@ class PlaybackConfiguration : public IPlaybackConfiguration, public muse::async: const SoundProfileName& fallbackSoundProfileStr() const; muse::async::Notification m_playNotesWhenEditingChanged; - + muse::async::Channel m_playChordWhenEditingChanged; + muse::async::Channel m_playHarmonyWhenEditingChanged; muse::async::Channel m_isAuxSendVisibleChanged; muse::async::Channel m_isAuxChannelVisibleChanged; muse::async::Channel m_isMixerSectionVisibleChanged; diff --git a/src/playback/iplaybackconfiguration.h b/src/playback/iplaybackconfiguration.h index bacddfd7cbbab..e58fec07a4b8b 100644 --- a/src/playback/iplaybackconfiguration.h +++ b/src/playback/iplaybackconfiguration.h @@ -40,9 +40,11 @@ class IPlaybackConfiguration : MODULE_EXPORT_INTERFACE virtual bool playChordWhenEditing() const = 0; virtual void setPlayChordWhenEditing(bool value) = 0; + virtual muse::async::Channel playChordWhenEditingChanged() const = 0; virtual bool playHarmonyWhenEditing() const = 0; virtual void setPlayHarmonyWhenEditing(bool value) = 0; + virtual muse::async::Channel playHarmonyWhenEditingChanged() const = 0; virtual PlaybackCursorType cursorType() const = 0; diff --git a/src/project/internal/projectconfiguration.cpp b/src/project/internal/projectconfiguration.cpp index 58b182f94da0a..f70dd8d8710cc 100644 --- a/src/project/internal/projectconfiguration.cpp +++ b/src/project/internal/projectconfiguration.cpp @@ -114,7 +114,13 @@ void ProjectConfiguration::init() settings()->setDefaultValue(OPEN_DETAILED_PROJECT_UPLOADED_DIALOG, Val(true)); settings()->setDefaultValue(HAS_ASKED_AUDIO_GENERATION_SETTINGS, Val(false)); settings()->setDefaultValue(GENERATE_AUDIO_TIME_PERIOD_TYPE_KEY, Val(static_cast(GenerateAudioTimePeriodType::Never))); + settings()->valueChanged(GENERATE_AUDIO_TIME_PERIOD_TYPE_KEY).onReceive(nullptr, [this](const Val& val) { + m_generateAudioTimePeriodTypeChanged.send(val.toInt()); + }); settings()->setDefaultValue(NUMBER_OF_SAVES_TO_GENERATE_AUDIO_KEY, Val(10)); + settings()->valueChanged(NUMBER_OF_SAVES_TO_GENERATE_AUDIO_KEY).onReceive(nullptr, [this](const Val& val) { + m_numberOfSavesToGenerateAudioChanged.send(val.toInt()); + }); settings()->setDefaultValue(SHOW_CLOUD_IS_NOT_AVAILABLE_WARNING, Val(true)); settings()->setDefaultValue(DISABLE_VERSION_CHECKING, Val(false)); @@ -645,6 +651,11 @@ void ProjectConfiguration::setGenerateAudioTimePeriodType(GenerateAudioTimePerio settings()->setSharedValue(GENERATE_AUDIO_TIME_PERIOD_TYPE_KEY, Val(static_cast(type))); } +muse::async::Channel ProjectConfiguration::generateAudioTimePeriodTypeChanged() const +{ + return m_generateAudioTimePeriodTypeChanged; +} + int ProjectConfiguration::numberOfSavesToGenerateAudio() const { return settings()->value(NUMBER_OF_SAVES_TO_GENERATE_AUDIO_KEY).toInt(); @@ -655,6 +666,11 @@ void ProjectConfiguration::setNumberOfSavesToGenerateAudio(int number) settings()->setSharedValue(NUMBER_OF_SAVES_TO_GENERATE_AUDIO_KEY, Val(number)); } +muse::async::Channel ProjectConfiguration::numberOfSavesToGenerateAudioChanged() const +{ + return m_numberOfSavesToGenerateAudioChanged; +} + muse::io::path_t ProjectConfiguration::temporaryMp3FilePathTemplate() const { return globalConfiguration()->userAppDataPath() + "/audioFile_XXXXXX.mp3"; diff --git a/src/project/internal/projectconfiguration.h b/src/project/internal/projectconfiguration.h index d82694f56da65..b2a28564c4158 100644 --- a/src/project/internal/projectconfiguration.h +++ b/src/project/internal/projectconfiguration.h @@ -142,8 +142,11 @@ class ProjectConfiguration : public IProjectConfiguration GenerateAudioTimePeriodType generateAudioTimePeriodType() const override; void setGenerateAudioTimePeriodType(GenerateAudioTimePeriodType type) override; + muse::async::Channel generateAudioTimePeriodTypeChanged() const override; + int numberOfSavesToGenerateAudio() const override; void setNumberOfSavesToGenerateAudio(int number) override; + muse::async::Channel numberOfSavesToGenerateAudioChanged() const override; muse::io::path_t temporaryMp3FilePathTemplate() const override; @@ -172,6 +175,9 @@ class ProjectConfiguration : public IProjectConfiguration muse::async::Channel m_autoSaveEnabledChanged; muse::async::Channel m_autoSaveIntervalChanged; + muse::async::Channel m_generateAudioTimePeriodTypeChanged; + muse::async::Channel m_numberOfSavesToGenerateAudioChanged; + muse::async::Channel m_alsoShareAudioComChanged; mutable std::map m_migrationOptions; diff --git a/src/project/iprojectconfiguration.h b/src/project/iprojectconfiguration.h index e7447745ff2a4..1e7115c4069df 100644 --- a/src/project/iprojectconfiguration.h +++ b/src/project/iprojectconfiguration.h @@ -147,9 +147,11 @@ class IProjectConfiguration : MODULE_EXPORT_INTERFACE virtual GenerateAudioTimePeriodType generateAudioTimePeriodType() const = 0; virtual void setGenerateAudioTimePeriodType(GenerateAudioTimePeriodType type) = 0; + virtual muse::async::Channel generateAudioTimePeriodTypeChanged() const = 0; virtual int numberOfSavesToGenerateAudio() const = 0; virtual void setNumberOfSavesToGenerateAudio(int number) = 0; + virtual muse::async::Channel numberOfSavesToGenerateAudioChanged() const = 0; virtual muse::io::path_t temporaryMp3FilePathTemplate() const = 0; diff --git a/src/project/qml/MuseScore/Project/AudioGenerationSettings.qml b/src/project/qml/MuseScore/Project/AudioGenerationSettings.qml index 483cb4dbcd1f2..edcf349c67f34 100644 --- a/src/project/qml/MuseScore/Project/AudioGenerationSettings.qml +++ b/src/project/qml/MuseScore/Project/AudioGenerationSettings.qml @@ -55,6 +55,10 @@ RadioButtonGroup { id: settingsModel } + Component.onCompleted: { + settingsModel.load() + } + model: [ { text: qsTrc("project/save", "Never"), type: GenerateAudioTimePeriodType.Never }, { text: qsTrc("project/save", "Always"), type: GenerateAudioTimePeriodType.Always }, diff --git a/src/project/tests/mocks/projectconfigurationmock.h b/src/project/tests/mocks/projectconfigurationmock.h index c55aee2c80430..b6096bd05c6e4 100644 --- a/src/project/tests/mocks/projectconfigurationmock.h +++ b/src/project/tests/mocks/projectconfigurationmock.h @@ -124,9 +124,11 @@ class ProjectConfigurationMock : public project::IProjectConfiguration MOCK_METHOD(GenerateAudioTimePeriodType, generateAudioTimePeriodType, (), (const, override)); MOCK_METHOD(void, setGenerateAudioTimePeriodType, (GenerateAudioTimePeriodType), (override)); + MOCK_METHOD(muse::async::Channel, generateAudioTimePeriodTypeChanged, (), (const, override)); MOCK_METHOD(int, numberOfSavesToGenerateAudio, (), (const, override)); MOCK_METHOD(void, setNumberOfSavesToGenerateAudio, (int), (override)); + MOCK_METHOD(muse::async::Channel, numberOfSavesToGenerateAudioChanged, (), (const, override)); MOCK_METHOD(muse::io::path_t, temporaryMp3FilePathTemplate, (), (const, override)); diff --git a/src/project/view/audiogenerationsettingsmodel.cpp b/src/project/view/audiogenerationsettingsmodel.cpp index d12b628ab41b6..02d8833a38bd7 100644 --- a/src/project/view/audiogenerationsettingsmodel.cpp +++ b/src/project/view/audiogenerationsettingsmodel.cpp @@ -29,6 +29,17 @@ AudioGenerationSettingsModel::AudioGenerationSettingsModel(QObject* parent) { } +void AudioGenerationSettingsModel::load() +{ + configuration()->generateAudioTimePeriodTypeChanged().onReceive(this, [this](int) { + emit timePeriodTypeChanged(); + }); + + configuration()->numberOfSavesToGenerateAudioChanged().onReceive(this, [this](int) { + emit numberOfSavesChanged(); + }); +} + int AudioGenerationSettingsModel::timePeriodType() const { return static_cast(configuration()->generateAudioTimePeriodType()); diff --git a/src/project/view/audiogenerationsettingsmodel.h b/src/project/view/audiogenerationsettingsmodel.h index 34a4e08ab6eaa..0ba5abe3e88de 100644 --- a/src/project/view/audiogenerationsettingsmodel.h +++ b/src/project/view/audiogenerationsettingsmodel.h @@ -28,7 +28,7 @@ #include "iprojectconfiguration.h" namespace mu::project { -class AudioGenerationSettingsModel : public QObject +class AudioGenerationSettingsModel : public QObject, public muse::async::Asyncable { Q_OBJECT @@ -40,6 +40,8 @@ class AudioGenerationSettingsModel : public QObject public: explicit AudioGenerationSettingsModel(QObject* parent = nullptr); + Q_INVOKABLE void load(); + int timePeriodType() const; int numberOfSaves() const; diff --git a/src/stubs/notation/notationconfigurationstub.cpp b/src/stubs/notation/notationconfigurationstub.cpp index e4f6197c617bc..b4b3d058f7e3c 100644 --- a/src/stubs/notation/notationconfigurationstub.cpp +++ b/src/stubs/notation/notationconfigurationstub.cpp @@ -164,6 +164,12 @@ void NotationConfigurationStub::setSelectionProximity(int) { } +muse::async::Channel NotationConfigurationStub::selectionProximityChanged() const +{ + static muse::async::Channel ch; + return ch; +} + ZoomType NotationConfigurationStub::defaultZoomType() const { return ZoomType::PageWidth; @@ -182,6 +188,12 @@ void NotationConfigurationStub::setDefaultZoom(int) { } +muse::async::Notification NotationConfigurationStub::defaultZoomChanged() const +{ + static muse::async::Notification n; + return n; +} + QList NotationConfigurationStub::possibleZoomPercentageList() const { return QList(); @@ -206,6 +218,12 @@ void NotationConfigurationStub::setMouseZoomPrecision(int) { } +muse::async::Notification NotationConfigurationStub::mouseZoomPrecisionChanged() const +{ + static muse::async::Notification n; + return n; +} + std::string NotationConfigurationStub::fontFamily() const { return std::string(); @@ -240,6 +258,12 @@ void NotationConfigurationStub::setDefaultStyleFilePath(const muse::io::path_t&) { } +muse::async::Channel NotationConfigurationStub::defaultStyleFilePathChanged() const +{ + static muse::async::Channel ch; + return ch; +} + muse::io::path_t NotationConfigurationStub::partStyleFilePath() const { return muse::io::path_t(); @@ -249,6 +273,12 @@ void NotationConfigurationStub::setPartStyleFilePath(const muse::io::path_t&) { } +muse::async::Channel NotationConfigurationStub::partStyleFilePathChanged() const +{ + static muse::async::Channel ch; + return ch; +} + bool NotationConfigurationStub::isMidiInputEnabled() const { return false; @@ -359,6 +389,12 @@ void NotationConfigurationStub::setColorNotesOutsideOfUsablePitchRange(bool) { } +muse::async::Channel NotationConfigurationStub::colorNotesOutsideOfUsablePitchRangeChanged() const +{ + static muse::async::Channel ch; + return ch; +} + int NotationConfigurationStub::delayBetweenNotesInRealTimeModeMilliseconds() const { return 100; @@ -368,6 +404,12 @@ void NotationConfigurationStub::setDelayBetweenNotesInRealTimeModeMilliseconds(i { } +muse::async::Channel NotationConfigurationStub::delayBetweenNotesInRealTimeModeMillisecondsChanged() const +{ + static muse::async::Channel ch; + return ch; +} + int NotationConfigurationStub::notePlayDurationMilliseconds() const { return 100; @@ -377,6 +419,12 @@ void NotationConfigurationStub::setNotePlayDurationMilliseconds(int) { } +muse::async::Channel NotationConfigurationStub::notePlayDurationMillisecondsChanged() const +{ + static muse::async::Channel ch; + return ch; +} + void NotationConfigurationStub::setTemplateModeEnabled(std::optional) { } @@ -543,3 +591,9 @@ muse::io::path_t NotationConfigurationStub::styleFileImportPath() const void NotationConfigurationStub::setStyleFileImportPath(const muse::io::path_t&) { } + +muse::async::Channel NotationConfigurationStub::styleFileImportPathChanged() const +{ + static muse::async::Channel ch; + return ch; +} diff --git a/src/stubs/notation/notationconfigurationstub.h b/src/stubs/notation/notationconfigurationstub.h index f02f0bf5018ab..d8e7e9c52c8dd 100644 --- a/src/stubs/notation/notationconfigurationstub.h +++ b/src/stubs/notation/notationconfigurationstub.h @@ -75,6 +75,7 @@ class NotationConfigurationStub : public INotationConfiguration int selectionProximity() const override; void setSelectionProximity(int proximity) override; + muse::async::Channel selectionProximityChanged() const override; ZoomType defaultZoomType() const override; void setDefaultZoomType(ZoomType zoomType) override; @@ -82,6 +83,8 @@ class NotationConfigurationStub : public INotationConfiguration int defaultZoom() const override; void setDefaultZoom(int zoomPercentage) override; + muse::async::Notification defaultZoomChanged() const override; + QList possibleZoomPercentageList() const override; qreal scalingFromZoomPercentage(int zoomPercentage) const override; @@ -89,6 +92,7 @@ class NotationConfigurationStub : public INotationConfiguration int mouseZoomPrecision() const override; void setMouseZoomPrecision(int precision) override; + muse::async::Notification mouseZoomPrecisionChanged() const override; std::string fontFamily() const override; int fontSize() const override; @@ -99,9 +103,11 @@ class NotationConfigurationStub : public INotationConfiguration muse::io::path_t defaultStyleFilePath() const override; void setDefaultStyleFilePath(const muse::io::path_t& path) override; + muse::async::Channel defaultStyleFilePathChanged() const override; muse::io::path_t partStyleFilePath() const override; void setPartStyleFilePath(const muse::io::path_t& path) override; + muse::async::Channel partStyleFilePathChanged() const override; bool isMidiInputEnabled() const override; void setIsMidiInputEnabled(bool enabled) override; @@ -135,12 +141,15 @@ class NotationConfigurationStub : public INotationConfiguration bool colorNotesOutsideOfUsablePitchRange() const override; void setColorNotesOutsideOfUsablePitchRange(bool value) override; + muse::async::Channel colorNotesOutsideOfUsablePitchRangeChanged() const override; int delayBetweenNotesInRealTimeModeMilliseconds() const override; void setDelayBetweenNotesInRealTimeModeMilliseconds(int delayMs) override; + muse::async::Channel delayBetweenNotesInRealTimeModeMillisecondsChanged() const override; int notePlayDurationMilliseconds() const override; void setNotePlayDurationMilliseconds(int durationMs) override; + muse::async::Channel notePlayDurationMillisecondsChanged() const override; void setTemplateModeEnabled(std::optional enabled) override; void setTestModeEnabled(std::optional enabled) override; @@ -192,6 +201,7 @@ class NotationConfigurationStub : public INotationConfiguration muse::io::path_t styleFileImportPath() const override; void setStyleFileImportPath(const muse::io::path_t& path) override; + muse::async::Channel styleFileImportPathChanged() const override; }; } diff --git a/src/stubs/playback/playbackconfigurationstub.cpp b/src/stubs/playback/playbackconfigurationstub.cpp index 8060fbfefc62d..61f069f9ad221 100644 --- a/src/stubs/playback/playbackconfigurationstub.cpp +++ b/src/stubs/playback/playbackconfigurationstub.cpp @@ -47,6 +47,12 @@ void PlaybackConfigurationStub::setPlayChordWhenEditing(bool) { } +muse::async::Channel PlaybackConfigurationStub::playChordWhenEditingChanged() const +{ + static muse::async::Channel ch; + return ch; +} + bool PlaybackConfigurationStub::playHarmonyWhenEditing() const { return false; @@ -56,6 +62,12 @@ void PlaybackConfigurationStub::setPlayHarmonyWhenEditing(bool) { } +muse::async::Channel PlaybackConfigurationStub::playHarmonyWhenEditingChanged() const +{ + static muse::async::Channel ch; + return ch; +} + PlaybackCursorType PlaybackConfigurationStub::cursorType() const { return PlaybackCursorType::SMOOTH; diff --git a/src/stubs/playback/playbackconfigurationstub.h b/src/stubs/playback/playbackconfigurationstub.h index 39edce1e1c20a..9059819e6a5dd 100644 --- a/src/stubs/playback/playbackconfigurationstub.h +++ b/src/stubs/playback/playbackconfigurationstub.h @@ -34,9 +34,11 @@ class PlaybackConfigurationStub : public IPlaybackConfiguration bool playChordWhenEditing() const override; void setPlayChordWhenEditing(bool value) override; + muse::async::Channel playChordWhenEditingChanged() const override; bool playHarmonyWhenEditing() const override; void setPlayHarmonyWhenEditing(bool value) override; + muse::async::Channel playHarmonyWhenEditingChanged() const override; PlaybackCursorType cursorType() const override; diff --git a/src/stubs/project/projectconfigurationstub.cpp b/src/stubs/project/projectconfigurationstub.cpp index 2071f125899c8..191e04a3746cc 100644 --- a/src/stubs/project/projectconfigurationstub.cpp +++ b/src/stubs/project/projectconfigurationstub.cpp @@ -296,6 +296,12 @@ void ProjectConfigurationStub::setGenerateAudioTimePeriodType(GenerateAudioTimeP { } +muse::async::Channel ProjectConfigurationStub::generateAudioTimePeriodTypeChanged() const +{ + static muse::async::Channel ch; + return ch; +} + int ProjectConfigurationStub::numberOfSavesToGenerateAudio() const { return 1; @@ -305,6 +311,12 @@ void ProjectConfigurationStub::setNumberOfSavesToGenerateAudio(int) { } +muse::async::Channel ProjectConfigurationStub::numberOfSavesToGenerateAudioChanged() const +{ + static muse::async::Channel ch; + return ch; +} + muse::io::path_t ProjectConfigurationStub::temporaryMp3FilePathTemplate() const { return muse::io::path_t(); diff --git a/src/stubs/project/projectconfigurationstub.h b/src/stubs/project/projectconfigurationstub.h index 86b1f2bf21ea8..10b3d93c8b0cc 100644 --- a/src/stubs/project/projectconfigurationstub.h +++ b/src/stubs/project/projectconfigurationstub.h @@ -115,9 +115,11 @@ class ProjectConfigurationStub : public IProjectConfiguration GenerateAudioTimePeriodType generateAudioTimePeriodType() const override; void setGenerateAudioTimePeriodType(GenerateAudioTimePeriodType type) override; + muse::async::Channel generateAudioTimePeriodTypeChanged() const override; int numberOfSavesToGenerateAudio() const override; void setNumberOfSavesToGenerateAudio(int number) override; + muse::async::Channel numberOfSavesToGenerateAudioChanged() const override; muse::io::path_t temporaryMp3FilePathTemplate() const override;