diff --git a/src/framework/cloud/qml/Muse/Cloud/CloudScoresView.qml b/src/framework/cloud/qml/Muse/Cloud/CloudScoresView.qml
index 0682acc58ab4a..f5d3c32d44c6d 100644
--- a/src/framework/cloud/qml/Muse/Cloud/CloudScoresView.qml
+++ b/src/framework/cloud/qml/Muse/Cloud/CloudScoresView.qml
@@ -217,7 +217,7 @@ ScoresView {
anchors.rightMargin: root.sideMargin
title: qsTrc("project", "Unable to load online scores")
- body: qsTrc("project", "Please check your internet connection or try again later.")
+ body: qsTrc("global", "Please check your internet connection or try again later.")
}
}
}
diff --git a/src/framework/learn/qml/Muse/Learn/internal/Playlist.qml b/src/framework/learn/qml/Muse/Learn/internal/Playlist.qml
index af259c2dee11d..0c84f538997c2 100644
--- a/src/framework/learn/qml/Muse/Learn/internal/Playlist.qml
+++ b/src/framework/learn/qml/Muse/Learn/internal/Playlist.qml
@@ -139,7 +139,7 @@ FocusScope {
StyledTextLabel {
width: parent.width
- text: qsTrc("learn", "Please check your internet connection or try again later.")
+ text: qsTrc("global", "Please check your internet connection or try again later.")
}
}
}
diff --git a/src/musesounds/CMakeLists.txt b/src/musesounds/CMakeLists.txt
index f8a54f02efbb2..544785354e9e1 100644
--- a/src/musesounds/CMakeLists.txt
+++ b/src/musesounds/CMakeLists.txt
@@ -4,7 +4,7 @@
# MuseScore
# Music Composition & Notation
#
-# Copyright (C) 2021 MuseScore BVBA and others
+# Copyright (C) 2024 MuseScore BVBA and others
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
@@ -26,6 +26,14 @@ set(MODULE_QML_IMPORT ${CMAKE_CURRENT_LIST_DIR}/qml)
set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/musesoundsmodule.cpp
${CMAKE_CURRENT_LIST_DIR}/musesoundsmodule.h
+ ${CMAKE_CURRENT_LIST_DIR}/imusesoundsrepository.h
+ ${CMAKE_CURRENT_LIST_DIR}/imusesoundsconfiguration.h
+ ${CMAKE_CURRENT_LIST_DIR}/musesoundstypes.h
+
+ ${CMAKE_CURRENT_LIST_DIR}/internal/musesoundsrepository.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/internal/musesoundsrepository.h
+ ${CMAKE_CURRENT_LIST_DIR}/internal/musesoundsconfiguration.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/internal/musesoundsconfiguration.h
${CMAKE_CURRENT_LIST_DIR}/view/musesoundslistmodel.cpp
${CMAKE_CURRENT_LIST_DIR}/view/musesoundslistmodel.h
diff --git a/src/musesounds/imusesoundsconfiguration.h b/src/musesounds/imusesoundsconfiguration.h
new file mode 100644
index 0000000000000..5411705ee250e
--- /dev/null
+++ b/src/musesounds/imusesoundsconfiguration.h
@@ -0,0 +1,40 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-CLA-applies
+ *
+ * MuseScore
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2024 MuseScore BVBA and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+
+#include "modularity/imoduleinterface.h"
+
+#include "network/networktypes.h"
+
+namespace mu::musesounds {
+class IMuseSoundsConfiguration : MODULE_EXPORT_INTERFACE
+{
+ INTERFACE_ID(IMuseSoundsConfiguration)
+
+public:
+ virtual ~IMuseSoundsConfiguration() = default;
+
+ virtual muse::network::RequestHeaders headers() const = 0;
+
+ virtual QUrl soundsUrl() const = 0;
+};
+}
diff --git a/src/musesounds/imusesoundsrepository.h b/src/musesounds/imusesoundsrepository.h
new file mode 100644
index 0000000000000..23db3b5109871
--- /dev/null
+++ b/src/musesounds/imusesoundsrepository.h
@@ -0,0 +1,40 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-CLA-applies
+ *
+ * MuseScore
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2024 MuseScore BVBA and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+
+#include "modularity/imoduleinterface.h"
+
+#include "async/notification.h"
+#include "musesoundstypes.h"
+
+namespace mu::musesounds {
+class IMuseSoundsRepository : MODULE_EXPORT_INTERFACE
+{
+ INTERFACE_ID(IMuseSoundsRepository)
+
+public:
+ virtual ~IMuseSoundsRepository() = default;
+
+ virtual const MuseSoundCategoryInfoList& soundsCategoryList() const = 0;
+ virtual muse::async::Notification soundsCategoryListChanged() const = 0;
+};
+}
diff --git a/src/musesounds/internal/musesoundsconfiguration.cpp b/src/musesounds/internal/musesoundsconfiguration.cpp
new file mode 100644
index 0000000000000..2eed98c5633d5
--- /dev/null
+++ b/src/musesounds/internal/musesoundsconfiguration.cpp
@@ -0,0 +1,54 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-CLA-applies
+ *
+ * MuseScore
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2024 MuseScore BVBA and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include "musesoundsconfiguration.h"
+
+#include "settings.h"
+
+using namespace mu::musesounds;
+using namespace muse;
+using namespace muse::network;
+
+static const std::string module_name("musesounds");
+static const Settings::Key GET_SOUNDS_TESTING_MODE_KEY(module_name, "musesounds/getSoundsTestingMode");
+
+void MuseSoundsConfiguration::init()
+{
+ settings()->setDefaultValue(GET_SOUNDS_TESTING_MODE_KEY, Val(false));
+}
+
+RequestHeaders MuseSoundsConfiguration::headers() const
+{
+ RequestHeaders headers;
+ headers.rawHeaders["Accept"] = "application/json";
+ return headers;
+}
+
+QUrl MuseSoundsConfiguration::soundsUrl() const
+{
+ return !isTestingMode() ? QUrl("https://cosmos-customer-webservice.azurewebsites.net/graphql")
+ : QUrl("https://cosmos-customer-webservice-dev.azurewebsites.net/graphql");
+}
+
+bool MuseSoundsConfiguration::isTestingMode() const
+{
+ return settings()->value(GET_SOUNDS_TESTING_MODE_KEY).toBool();
+}
diff --git a/src/musesounds/internal/musesoundsconfiguration.h b/src/musesounds/internal/musesoundsconfiguration.h
new file mode 100644
index 0000000000000..f239363033621
--- /dev/null
+++ b/src/musesounds/internal/musesoundsconfiguration.h
@@ -0,0 +1,47 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-CLA-applies
+ *
+ * MuseScore
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2024 MuseScore BVBA and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+
+#include "modularity/ioc.h"
+#include "iglobalconfiguration.h"
+
+#include "imusesoundsconfiguration.h"
+
+namespace mu::musesounds {
+class MuseSoundsConfiguration : public IMuseSoundsConfiguration, public muse::Injectable
+{
+ Inject globalConfiguration = { this };
+
+public:
+ MuseSoundsConfiguration(const muse::modularity::ContextPtr& iocCtx)
+ : Injectable(iocCtx) {}
+
+ void init();
+
+ muse::network::RequestHeaders headers() const override;
+
+ QUrl soundsUrl() const override;
+
+private:
+ bool isTestingMode() const;
+};
+}
diff --git a/src/musesounds/internal/musesoundsrepository.cpp b/src/musesounds/internal/musesoundsrepository.cpp
new file mode 100644
index 0000000000000..00944dab20bba
--- /dev/null
+++ b/src/musesounds/internal/musesoundsrepository.cpp
@@ -0,0 +1,149 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-CLA-applies
+ *
+ * MuseScore
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2024 MuseScore BVBA and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "musesoundsrepository.h"
+
+#include "serialization/json.h"
+
+#include "global/concurrency/concurrent.h"
+
+using namespace mu::musesounds;
+using namespace muse;
+using namespace muse::network;
+
+void MuseSoundsRepository::init()
+{
+ auto soundsCallBack = [this](const RetVal& result) {
+ if (!result.ret) {
+ LOGE() << result.ret.toString();
+ return;
+ }
+
+ LOGE() << result.ret.toString();
+
+ m_soundsCategories = result.val;
+ m_soundsCategoriesChanged.notify();
+ };
+
+ Concurrent::run(this, &MuseSoundsRepository::th_requestSounds, soundsRequestUrl(), soundsCallBack);
+}
+
+const MuseSoundCategoryInfoList& MuseSoundsRepository::soundsCategoryList() const
+{
+ return m_soundsCategories;
+}
+
+async::Notification MuseSoundsRepository::soundsCategoryListChanged() const
+{
+ return m_soundsCategoriesChanged;
+}
+
+QUrl MuseSoundsRepository::soundsRequestUrl() const
+{
+ String locale = QLocale().name();
+
+ String query = String(
+ R"(
+ query MyQuery {
+ product_pages_configuration(version: "default") {
+ librariesPageSections {
+ ... on ProductPageSectionRegular {
+ title(locale: {locale: "%1"})
+ productCards {
+ ... on ProductCardRegular {
+ title(locale: {locale: "%1"})
+ coverImageUrl
+ description(locale: {locale: "%1"})
+ }
+ }
+ }
+ }
+ }
+ }
+ )").arg(locale);
+
+ StringList params = {
+ "query=" + query
+ };
+
+ QUrl url = configuration()->soundsUrl();
+ url.setQuery(params.join(u"&"));
+
+ return url;
+}
+
+void MuseSoundsRepository::th_requestSounds(const QUrl& soundsUrl, std::function)> callBack) const
+{
+ TRACEFUNC;
+
+ network::INetworkManagerPtr networkManager = networkManagerCreator()->makeNetworkManager();
+ RequestHeaders headers = configuration()->headers();
+
+ QBuffer soundsInfoData;
+ Ret soundsItemsRet = networkManager->get(soundsUrl, &soundsInfoData, headers);
+ if (!soundsItemsRet) {
+ callBack(soundsItemsRet);
+ return;
+ }
+
+ JsonDocument soundsInfoDoc = JsonDocument::fromJson(ByteArray::fromQByteArray(soundsInfoData.data()));
+
+ RetVal result;
+ result.ret = make_ret(Ret::Code::Ok);
+ result.val = parseSounds(soundsInfoDoc);
+
+ callBack(result);
+}
+
+MuseSoundCategoryInfoList MuseSoundsRepository::parseSounds(const JsonDocument& soundsDoc) const
+{
+ MuseSoundCategoryInfoList result;
+
+ JsonObject obj = soundsDoc.rootObject();
+ JsonObject data = !obj.empty() ? obj.value("data").toObject() : JsonObject();
+ JsonObject productsSearch = !data.empty() ? data.value("products_search").toObject() : JsonObject();
+ JsonArray items = !productsSearch.empty() ? productsSearch.value("items").toArray() : JsonArray();
+
+ for (size_t i = 0; i < items.size(); i++) {
+ JsonObject itemObj = items.at(i).toObject();
+
+ MuseSoundCategoryInfo category;
+ category.title = itemObj.value("title").toString();
+
+ JsonArray soundsItems = itemObj.value("items").toArray();
+
+ for (size_t i = 0; i < soundsItems.size(); i++) {
+ JsonObject soundItemObj = soundsItems.at(i).toObject();
+
+ MuseSoundInfo sound;
+ sound.title = itemObj.value("title").toString();
+ sound.description = itemObj.value("description").toString();
+ sound.thumbnail = itemObj.value("coverImageUrl").toString();
+
+ category.sounds.emplace_back(sound);
+ }
+
+ result.emplace_back(category);
+ }
+
+ return result;
+}
diff --git a/src/musesounds/internal/musesoundsrepository.h b/src/musesounds/internal/musesoundsrepository.h
new file mode 100644
index 0000000000000..b7940a61839f2
--- /dev/null
+++ b/src/musesounds/internal/musesoundsrepository.h
@@ -0,0 +1,59 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-CLA-applies
+ *
+ * MuseScore
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2024 MuseScore BVBA and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#include "modularity/ioc.h"
+#include "network/inetworkmanagercreator.h"
+#include "imusesoundsconfiguration.h"
+
+#include "imusesoundsrepository.h"
+
+namespace muse {
+class JsonDocument;
+}
+
+namespace mu::musesounds {
+class MuseSoundsRepository : public IMuseSoundsRepository, public muse::Injectable
+{
+ Inject networkManagerCreator = { this };
+ Inject configuration = { this };
+
+public:
+ MuseSoundsRepository(const muse::modularity::ContextPtr& iocCtx)
+ : Injectable(iocCtx) {}
+
+ void init();
+
+ const MuseSoundCategoryInfoList& soundsCategoryList() const override;
+ muse::async::Notification soundsCategoryListChanged() const override;
+
+private:
+ QUrl soundsRequestUrl() const;
+ void th_requestSounds(const QUrl& soundsUrl, std::function)> callBack) const;
+
+ MuseSoundCategoryInfoList parseSounds(const muse::JsonDocument& soundsDoc) const;
+
+ MuseSoundCategoryInfoList m_soundsCategories;
+ muse::async::Notification m_soundsCategoriesChanged;
+};
+}
diff --git a/src/musesounds/musesoundsmodule.cpp b/src/musesounds/musesoundsmodule.cpp
index 5ceb3ecc5fc0e..3bb58d5f1605e 100644
--- a/src/musesounds/musesoundsmodule.cpp
+++ b/src/musesounds/musesoundsmodule.cpp
@@ -5,7 +5,7 @@
* MuseScore Studio
* Music Composition & Notation
*
- * Copyright (C) 2021 MuseScore Limited
+ * Copyright (C) 2024 MuseScore Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -23,6 +23,9 @@
#include
+#include "internal/musesoundsconfiguration.h"
+#include "internal/musesoundsrepository.h"
+
#include "view/musesoundslistmodel.h"
using namespace mu::musesounds;
@@ -40,6 +43,11 @@ std::string MuseSoundsModule::moduleName() const
void MuseSoundsModule::registerExports()
{
+ m_configuration = std::make_shared(iocContext());
+ m_repository = std::make_shared(iocContext());
+
+ ioc()->registerExport(moduleName(), m_configuration);
+ ioc()->registerExport(moduleName(), m_repository);
}
void MuseSoundsModule::resolveImports()
@@ -53,9 +61,15 @@ void MuseSoundsModule::registerResources()
void MuseSoundsModule::registerUiTypes()
{
- qmlRegisterType("MuseScore.AppShell", 1, 0, "MuseSoundsListModel");
+ qmlRegisterType("MuseScore.MuseSounds", 1, 0, "MuseSoundsListModel");
}
-void MuseSoundsModule::onInit(const IApplication::RunMode&)
+void MuseSoundsModule::onInit(const IApplication::RunMode& mode)
{
+ if (mode != IApplication::RunMode::GuiApp) {
+ return;
+ }
+
+ m_configuration->init();
+ m_repository->init();
}
diff --git a/src/musesounds/musesoundsmodule.h b/src/musesounds/musesoundsmodule.h
index 1a452b1941e30..606e47bd9f926 100644
--- a/src/musesounds/musesoundsmodule.h
+++ b/src/musesounds/musesoundsmodule.h
@@ -5,7 +5,7 @@
* MuseScore Studio
* Music Composition & Notation
*
- * Copyright (C) 2021 MuseScore Limited
+ * Copyright (C) 2024 MuseScore Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -27,6 +27,8 @@
#include "modularity/imodulesetup.h"
namespace mu::musesounds {
+class MuseSoundsConfiguration;
+class MuseSoundsRepository;
class MuseSoundsModule : public muse::modularity::IModuleSetup
{
public:
@@ -37,5 +39,9 @@ class MuseSoundsModule : public muse::modularity::IModuleSetup
void registerResources() override;
void registerUiTypes() override;
void onInit(const muse::IApplication::RunMode& mode) override;
+
+private:
+ std::shared_ptr m_configuration;
+ std::shared_ptr m_repository;
};
}
diff --git a/src/musesounds/musesoundstypes.h b/src/musesounds/musesoundstypes.h
new file mode 100644
index 0000000000000..126567b816b56
--- /dev/null
+++ b/src/musesounds/musesoundstypes.h
@@ -0,0 +1,41 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-CLA-applies
+ *
+ * MuseScore
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2024 MuseScore BVBA and others
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+
+#include "types/string.h"
+#include "io/path.h"
+
+namespace mu::musesounds {
+struct MuseSoundInfo {
+ muse::String title;
+ muse::String description;
+ muse::io::path_t thumbnail;
+};
+using MuseSoundInfoList = std::vector;
+
+struct MuseSoundCategoryInfo {
+ muse::String title;
+
+ MuseSoundInfoList sounds;
+};
+using MuseSoundCategoryInfoList = std::vector;
+}
diff --git a/src/musesounds/qml/MuseScore/MuseSounds/MuseSoundsPage.qml b/src/musesounds/qml/MuseScore/MuseSounds/MuseSoundsPage.qml
index bef14037a0f78..6940b3ca08b6c 100644
--- a/src/musesounds/qml/MuseScore/MuseSounds/MuseSoundsPage.qml
+++ b/src/musesounds/qml/MuseScore/MuseSounds/MuseSoundsPage.qml
@@ -5,7 +5,7 @@
* MuseScore Studio
* Music Composition & Notation
*
- * Copyright (C) 2021 MuseScore Limited
+ * Copyright (C) 2024 MuseScore Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -25,8 +25,9 @@ import QtQuick.Layouts 1.15
import Muse.Ui 1.0
import Muse.UiComponents 1.0
+import MuseScore.MuseSounds 1.0
-import MuseScore.AppShell 1.0
+import "internal"
FocusScope {
id: root
@@ -124,21 +125,20 @@ FocusScope {
spacing: 22
Repeater {
- model: museSoundsModel.categories
+ model: museSoundsModel
delegate: MuseSoundsListView {
width: parent.width
+
title: modelData.title
visible: count > 0
- categoryId: modelData.id
-
- model: museSoundsModel
+ model: modelData.sounds
flickableItem: column
navigationPanel.section: navSec
- navigationPanel.name: categoryId + "Sounds"
+ navigationPanel.name: title + "Sounds"
navigationPanel.order: index
onGetSoundRequested: {
@@ -153,6 +153,30 @@ FocusScope {
}
}
+ Column {
+ id: errorMessageColumn
+ visible: museSoundsModel.isEmpty
+
+ anchors.top: parent.top
+ //! NOTE: should be synchronized with the error message from Learn page
+ anchors.topMargin: 127 + topGradient.height + Math.max(parent.height / 3 - height / 2, 0)
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ spacing: 16
+
+ StyledTextLabel {
+ width: parent.width
+ font: ui.theme.tabBoldFont
+ text: qsTrc("musesounds", "Sorry, we are unable to load these sounds right now")
+ }
+
+ StyledTextLabel {
+ width: parent.width
+ text: qsTrc("global", "Please check your internet connection or try again later.")
+ }
+ }
+
GradientRectangle {
id: bottomGradient
anchors.left: parent.left
diff --git a/src/musesounds/qml/MuseScore/MuseSounds/internal/MuseSoundItem.qml b/src/musesounds/qml/MuseScore/MuseSounds/internal/MuseSoundItem.qml
index 3f5ce5a3d31b8..2be98ad3cb7f2 100644
--- a/src/musesounds/qml/MuseScore/MuseSounds/internal/MuseSoundItem.qml
+++ b/src/musesounds/qml/MuseScore/MuseSounds/internal/MuseSoundItem.qml
@@ -5,7 +5,7 @@
* MuseScore
* Music Composition & Notation
*
- * Copyright (C) 2021 MuseScore BVBA and others
+ * Copyright (C) 2024 MuseScore BVBA and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
diff --git a/src/musesounds/qml/MuseScore/MuseSounds/internal/MuseSoundsListView.qml b/src/musesounds/qml/MuseScore/MuseSounds/internal/MuseSoundsListView.qml
index 77336a6363227..1f020fab37a22 100644
--- a/src/musesounds/qml/MuseScore/MuseSounds/internal/MuseSoundsListView.qml
+++ b/src/musesounds/qml/MuseScore/MuseSounds/internal/MuseSoundsListView.qml
@@ -5,7 +5,7 @@
* MuseScore
* Music Composition & Notation
*
- * Copyright (C) 2021 MuseScore BVBA and others
+ * Copyright (C) 2024 MuseScore BVBA and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -28,13 +28,11 @@ import Muse.Extensions 1.0
Column {
id: root
- property alias model: filterModel.sourceModel
+ property alias model: view.model
readonly property alias count: view.count
property alias title: titleLabel.text
- property string categoryId: ""
-
property var flickableItem: null
property int headerHeight: titleLabel.height + spacing
@@ -57,18 +55,6 @@ Column {
view.itemAtIndex(0).requestActive()
}
- SortFilterProxyModel {
- id: filterModel
-
- filters: [
- FilterValue {
- roleName: "categoryId"
- roleValue: root.categoryId
- compareType: CompareType.Contains
- }
- ]
- }
-
StyledTextLabel {
id: titleLabel
width: parent.width
@@ -88,8 +74,6 @@ Column {
height: contentHeight - spacingBetweenRows
- model: filterModel
-
// We don't want this GridView to be scrollable; it would conflict with the containing Flickable.
interactive: false
highlightFollowsCurrentItem: false // prevent automatic scrolling
@@ -110,11 +94,11 @@ Column {
width: view.cellWidth
function requestActive() {
- _item.navigation.requestActive()
+ soundItem.navigation.requestActive()
}
MuseSoundItem {
- id: _item
+ id: soundItem
width: view.actualCellWidth
height: view.actualCellHeight
@@ -130,8 +114,8 @@ Column {
navigation.row: view.columns === 0 ? 0 : Math.floor(model.index / view.columns)
navigation.column: model.index - (navigation.row * view.columns)
navigation.onActiveChanged: {
- var pos = _item.mapToItem(root.flickableItem, 0, 0)
- var rect = Qt.rect(pos.x, pos.y, _item.width, _item.height)
+ var pos = soundItem.mapToItem(root.flickableItem, 0, 0)
+ var rect = Qt.rect(pos.x, pos.y, soundItem.width, soundItem.height)
root.navigationActivated(rect)
}
diff --git a/src/musesounds/view/musesoundslistmodel.cpp b/src/musesounds/view/musesoundslistmodel.cpp
index 99242a205a2ff..9a24d3b79e55c 100644
--- a/src/musesounds/view/musesoundslistmodel.cpp
+++ b/src/musesounds/view/musesoundslistmodel.cpp
@@ -5,7 +5,7 @@
* MuseScore Studio
* Music Composition & Notation
*
- * Copyright (C) 2021 MuseScore Limited
+ * Copyright (C) 2024 MuseScore Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -26,49 +26,38 @@
using namespace mu::musesounds;
-MuseSoundsListModel::MuseSoundsListModel(QObject* parent)
- : QAbstractListModel(parent), Injectable(muse::iocCtxForQmlObject(this))
+static const QVariantMap soundInfoToMap(const MuseSoundInfo& soundInfo)
{
+ QVariantMap map;
+ map["title"] = soundInfo.title.toQString();
+ map["description"] = soundInfo.description.toQString();
+ map["thumbnail"] = QUrl::fromLocalFile(soundInfo.thumbnail.toQString());
+
+ return map;
}
-void MuseSoundsListModel::load()
+static const QVariantList soundInfoListToVariantList(const MuseSoundInfoList& soundInfoList)
{
- beginResetModel();
-
- m_sounds = {
- { u"symphony-brass", u"Symphony Brass", u"The UK's finest brass players expertly recorded at the world-famous AIR Studios.", "",
- u"Trending" },
- { u"Harpsichord", u"Harpsichord", u"Performed by London harpsichord virtuoso Steven Devine.", "",
- u"Trending" },
- { u"Muse Woodwinds", u"Muse Woodwinds", u"A stunning collection of 17 solo woodwind instruments.", "",
- u"Trending" },
-
- { u"Muse Strings", u"Muse Strings", u"An incredible free collection of sectional and solo strings", "",
- u"Muse Group" },
- { u"Muse Keys", u"Muse Keys", u"An essential collection of keyboard instruments for use in your scores.", "",
- u"Muse Group" },
- { u"Muse Percussion", u"Muse Percussion", u"A huge battery of orchestral and epic percussion.", "",
- u"Muse Group" },
- { u"Muse Woodwinds", u"Muse Woodwinds", u"A stunning collection of 17 solo woodwind instruments.", "",
- u"Muse Group" }
- };
+ QVariantList list;
- std::sort(m_sounds.begin(), m_sounds.end(), [](const MuseSoundInfo& l, const MuseSoundInfo& r) {
- return l.order < r.order;
- });
+ for (const MuseSoundInfo& soundInfo : soundInfoList) {
+ list << soundInfoToMap(soundInfo);
+ }
- endResetModel();
+ return list;
+}
- m_categories = {
- { u"Trending", u"Trending", 0 },
- { u"Muse Group", u"Muse Group", 1 }
- };
+MuseSoundsListModel::MuseSoundsListModel(QObject* parent)
+ : QAbstractListModel(parent), Injectable(muse::iocCtxForQmlObject(this))
+{
+}
- std::sort(m_categories.begin(), m_categories.end(), [](const MuseSoundCategoryInfo& l, const MuseSoundCategoryInfo& r) {
- return l.order < r.order;
+void MuseSoundsListModel::load()
+{
+ setSoundsCategories(repository()->soundsCategoryList());
+ repository()->soundsCategoryListChanged().onNotify(this, [this](){
+ setSoundsCategories(repository()->soundsCategoryList());
});
-
- emit categoriesChanged();
}
QVariant MuseSoundsListModel::data(const QModelIndex& index, int role) const
@@ -77,23 +66,13 @@ QVariant MuseSoundsListModel::data(const QModelIndex& index, int role) const
return QVariant();
}
- MuseSoundInfo soundInfo = m_sounds.at(index.row());
+ const MuseSoundCategoryInfo& soundCategoryInfo = m_soundsCategories.at(index.row());
switch (role) {
- case rCode:
- return soundInfo.id.toQString();
case rTitle:
- return soundInfo.title.toQString();
- case rDescription:
- return soundInfo.description.toQString();
- case rThumbnailUrl:
- if (soundInfo.thumbnail.empty()) {
- return "qrc:/qml/Muse/Extensions/internal/resources/placeholder.png"; // todo
- }
-
- return QUrl::fromLocalFile(soundInfo.thumbnail.toQString());
- case rCategoryId:
- return soundInfo.categoryId.toQString();
+ return soundCategoryInfo.title.toQString();
+ case rSounds:
+ return soundInfoListToVariantList(soundCategoryInfo.sounds);
}
return QVariant();
@@ -101,31 +80,29 @@ QVariant MuseSoundsListModel::data(const QModelIndex& index, int role) const
int MuseSoundsListModel::rowCount(const QModelIndex&) const
{
- return static_cast(m_sounds.size());
+ return static_cast(m_soundsCategories.size());
}
QHash MuseSoundsListModel::roleNames() const
{
return {
- { rCode, "codeKey" },
{ rTitle, "title" },
- { rDescription, "description" },
- { rThumbnailUrl, "thumbnailUrl" },
- { rCategoryId, "categoryId" }
+ { rSounds, "sounds" }
};
}
-QVariantList MuseSoundsListModel::categories() const
+bool MuseSoundsListModel::isEmpty() const
{
- QVariantList result;
+ return m_soundsCategories.empty();
+}
+
+void MuseSoundsListModel::setSoundsCategories(const MuseSoundCategoryInfoList& soundsCategories)
+{
+ beginResetModel();
- for (const MuseSoundCategoryInfo& categoryInfo : m_categories) {
- QVariantMap obj;
- obj["id"] = categoryInfo.id.toQString();
- obj["title"] = categoryInfo.title.toQString();
+ m_soundsCategories = soundsCategories;
- result << obj;
- }
+ endResetModel();
- return result;
+ emit isEmptyChanged();
}
diff --git a/src/musesounds/view/musesoundslistmodel.h b/src/musesounds/view/musesoundslistmodel.h
index df19ddcb29421..29ca9045385ea 100644
--- a/src/musesounds/view/musesoundslistmodel.h
+++ b/src/musesounds/view/musesoundslistmodel.h
@@ -5,7 +5,7 @@
* MuseScore Studio
* Music Composition & Notation
*
- * Copyright (C) 2021 MuseScore Limited
+ * Copyright (C) 2024 MuseScore Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -24,37 +24,19 @@
#include
+#include "async/asyncable.h"
+
#include "modularity/ioc.h"
-#include "context/iglobalcontext.h"
-#include "iglobalconfiguration.h"
+#include "imusesoundsrepository.h"
namespace mu::musesounds {
-struct MuseSoundCategoryInfo {
- muse::String id;
- muse::String title;
- int order = -1;
-};
-using MuseSoundCategoryInfoList = std::vector;
-
-struct MuseSoundInfo {
- muse::String id;
- muse::String title;
- muse::String description;
- muse::io::path_t thumbnail;
- muse::String categoryId;
- int order = -1;
-};
-using MuseSoundInfoList = std::vector;
-
-class MuseSoundsListModel : public QAbstractListModel, public muse::Injectable
+class MuseSoundsListModel : public QAbstractListModel, public muse::async::Asyncable, public muse::Injectable
{
Q_OBJECT
- Q_PROPERTY(QVariantList categories READ categories NOTIFY categoriesChanged)
+ Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged)
- // Inject interactive = { this };
- // Inject provider = { this };
- // Inject configuration = { this };
+ Inject repository = { this };
public:
explicit MuseSoundsListModel(QObject* parent = nullptr);
@@ -65,21 +47,19 @@ class MuseSoundsListModel : public QAbstractListModel, public muse::Injectable
Q_INVOKABLE void load();
- QVariantList categories() const;
+ bool isEmpty() const;
signals:
- void categoriesChanged();
+ void isEmptyChanged();
private:
enum Roles {
- rCode = Qt::UserRole + 1,
- rTitle,
- rDescription,
- rThumbnailUrl,
- rCategoryId
+ rTitle = Qt::UserRole + 1,
+ rSounds
};
- MuseSoundInfoList m_sounds;
- MuseSoundCategoryInfoList m_categories;
+ void setSoundsCategories(const MuseSoundCategoryInfoList& soundsCategories);
+
+ MuseSoundCategoryInfoList m_soundsCategories;
};
}