From b66f2602f75ea891f1178533c6ddb82c3c1ed44b Mon Sep 17 00:00:00 2001
From: Casper Jeukendrup <48658420+cbjeukendrup@users.noreply.github.com>
Date: Thu, 7 May 2026 20:48:12 +0200
Subject: [PATCH] Move Home > Scores > Cloud scores components into project
module
Near all other Home > Scores components
---
.../qml/MuseScore/Project/CMakeLists.txt | 10 +-
.../qml/MuseScore/Project/ScoresPage.qml | 3 -
.../ScoresPage/CloudScoresGridView.qml | 110 ++++++
.../ScoresPage/CloudScoresListView.qml | 327 ++++++++++++++++++
.../internal/ScoresPage/CloudScoresView.qml | 221 ++++++++++++
.../ScoresPage}/ScoresGridView.qml | 2 -
.../ScoresPage}/ScoresListView.qml | 2 -
.../{ => internal/ScoresPage}/ScoresView.qml | 0
8 files changed, 665 insertions(+), 10 deletions(-)
create mode 100644 src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresGridView.qml
create mode 100644 src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresListView.qml
create mode 100644 src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresView.qml
rename src/project/qml/MuseScore/Project/{ => internal/ScoresPage}/ScoresGridView.qml (99%)
rename src/project/qml/MuseScore/Project/{ => internal/ScoresPage}/ScoresListView.qml (99%)
rename src/project/qml/MuseScore/Project/{ => internal/ScoresPage}/ScoresView.qml (100%)
diff --git a/src/project/qml/MuseScore/Project/CMakeLists.txt b/src/project/qml/MuseScore/Project/CMakeLists.txt
index 3a9c37bd50da8..d0a84c5175eba 100644
--- a/src/project/qml/MuseScore/Project/CMakeLists.txt
+++ b/src/project/qml/MuseScore/Project/CMakeLists.txt
@@ -98,9 +98,15 @@ qt_add_qml_module(project_qml
internal/Properties/PropertyItem.qml
internal/SaveToCloud/SaveLocationOption.qml
internal/ScoresPage/CloudScoreIndicatorButton.qml
+ internal/ScoresPage/CloudScoresGridView.qml
+ internal/ScoresPage/CloudScoresListView.qml
+ internal/ScoresPage/CloudScoresView.qml
internal/ScoresPage/RecentScoresView.qml
internal/ScoresPage/ScoreGridItem.qml
internal/ScoresPage/ScoreListItem.qml
+ internal/ScoresPage/ScoresGridView.qml
+ internal/ScoresPage/ScoresListView.qml
+ internal/ScoresPage/ScoresView.qml
internal/ScoresPage/ScoreThumbnail.qml
Message.qml
MigrationDialog.qml
@@ -108,10 +114,7 @@ qt_add_qml_module(project_qml
ProjectPropertiesDialog.qml
ProjectUploadedDialog.qml
SaveToCloudDialog.qml
- ScoresGridView.qml
- ScoresListView.qml
ScoresPage.qml
- ScoresView.qml
UploadProgressDialog.qml
RESOURCES
internal/Migration/migration.png
@@ -125,6 +128,7 @@ qt_add_qml_module(project_qml
resources/AudioCom_Waveform.png
resources/PublishScores.png
IMPORTS
+ TARGET muse_cloud_qml
TARGET muse_ui_qml
TARGET muse_uicomponents_qml
TARGET notationscene_qml
diff --git a/src/project/qml/MuseScore/Project/ScoresPage.qml b/src/project/qml/MuseScore/Project/ScoresPage.qml
index ab8177329399e..000a4d201d71c 100644
--- a/src/project/qml/MuseScore/Project/ScoresPage.qml
+++ b/src/project/qml/MuseScore/Project/ScoresPage.qml
@@ -25,9 +25,6 @@ import QtQuick.Layouts
import Muse.Ui
import Muse.UiComponents
import MuseScore.Project
-import Muse.Cloud
-
-import "internal/ScoresPage"
FocusScope {
id: root
diff --git a/src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresGridView.qml b/src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresGridView.qml
new file mode 100644
index 0000000000000..48fe49f877381
--- /dev/null
+++ b/src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresGridView.qml
@@ -0,0 +1,110 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-Studio-CLA-applies
+ *
+ * MuseScore Studio
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2023 MuseScore Limited 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 .
+ */
+import QtQuick
+
+import Muse.Ui
+import Muse.UiComponents
+import MuseScore.Project
+
+ScoresGridView {
+ id: root
+
+ navigation.name: "OnlineScoresGrid"
+ navigation.accessible.name: qsTrc("project", "Online scores grid")
+
+ isNoResultsMessageAllowed: model.state === CloudScoresModel.Fine
+
+ Component.onCompleted: {
+ prv.updateDesiredRowCount()
+ }
+
+ Connections {
+ target: root.model
+
+ function onStateChanged() {
+ if (root.model.state === CloudScoresModel.Fine) {
+ // After the model has loaded more, check if even more is needed
+ prv.updateDesiredRowCount();
+ }
+ }
+ }
+
+ QtObject {
+ id: prv
+
+ readonly property int remainingFullRowsBelowViewport:
+ Math.floor(root.view.count / root.view.columns) - Math.ceil((root.view.contentY + root.view.height) / root.view.cellHeight)
+
+ readonly property bool isSatisfied: remainingFullRowsBelowViewport >= 3
+
+ onIsSatisfiedChanged: {
+ if (!isSatisfied) {
+ updateDesiredRowCount();
+ }
+ }
+
+ property bool updateDesiredRowCountScheduled: false
+
+ function updateDesiredRowCount() {
+ if (updateDesiredRowCountScheduled) {
+ return
+ }
+
+ if (isSatisfied || !root.model.hasMore) {
+ return
+ }
+
+ updateDesiredRowCountScheduled = true
+
+ Qt.callLater(function() {
+ let newDesiredRowCount = root.model.rowCount + (3 - remainingFullRowsBelowViewport) * view.columns
+
+ if (root.model.desiredRowCount < newDesiredRowCount) {
+ root.model.desiredRowCount = newDesiredRowCount
+ }
+
+ updateDesiredRowCountScheduled = false
+ })
+ }
+ }
+
+ view.footer: root.model.state === CloudScoresModel.Loading
+ ? busyIndicatorComp : null
+
+ Component {
+ id: busyIndicatorComp
+
+ Item {
+ width: GridView.view ? GridView.view.width : 0
+ height: indicator.implicitHeight + indicator.anchors.topMargin + indicator.anchors.bottomMargin
+
+ StyledBusyIndicator {
+ id: indicator
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.topMargin: root.view.spacingBetweenRows / 2
+ anchors.bottomMargin: root.view.spacingBetweenRows / 2
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresListView.qml b/src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresListView.qml
new file mode 100644
index 0000000000000..ffa0b3641f33a
--- /dev/null
+++ b/src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresListView.qml
@@ -0,0 +1,327 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-Studio-CLA-applies
+ *
+ * MuseScore Studio
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2023 MuseScore Limited 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 .
+ */
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+import Muse.Ui
+import Muse.UiComponents
+import MuseScore.Project
+import Muse.Cloud
+
+ScoresListView {
+ id: root
+
+ navigation.name: "OnlineScoresList"
+ navigation.accessible.name: qsTrc("project", "Online scores list")
+
+ Component.onCompleted: {
+ prv.updateDesiredRowCount()
+ }
+
+ Connections {
+ target: root.model
+ function onStateChanged() {
+ if (root.model.state === CloudScoresModel.Fine) {
+ // After the model has loaded more, check if even more is needed
+ prv.updateDesiredRowCount();
+ }
+ }
+ }
+
+ QtObject {
+ id: prv
+
+ readonly property int remainingScoresBelowViewport:
+ root.view.count - Math.ceil((root.view.contentY + root.view.height) / root.view.rowHeight)
+
+ readonly property bool isSatisfied: remainingScoresBelowViewport >= 20
+
+ onIsSatisfiedChanged: {
+ if (!isSatisfied) {
+ updateDesiredRowCount();
+ }
+ }
+
+ property bool updateDesiredRowCountScheduled: false
+
+ function updateDesiredRowCount() {
+ if (updateDesiredRowCountScheduled) {
+ return
+ }
+
+ if (isSatisfied || !root.model.hasMore) {
+ return
+ }
+
+ updateDesiredRowCountScheduled = true
+
+ Qt.callLater(function() {
+ let newDesiredRowCount = root.model.rowCount + (20 - remainingScoresBelowViewport)
+
+ if (root.model.desiredRowCount < newDesiredRowCount) {
+ root.model.desiredRowCount = newDesiredRowCount
+ }
+
+ updateDesiredRowCountScheduled = false
+ })
+ }
+ }
+
+ columns: [
+ //! Note: sometimes, in the `delegate` item, some properties are used that don't seem to be defined:
+ //! `score`, `navigationPanel`, `navigationRow`, `navigationColumnStart`, `listItem`
+ //! These properties are provided by the `Loader` inside `columnsRepeater` in `ScoreListItem.qml`.
+
+ ScoresListView.ColumnItem {
+ id: visibilityColumn
+ header: qsTrc("project/cloud", "Visibility")
+
+ width: function(parentWidth) {
+ let parentWidthExclusingSpacing = parentWidth - root.columns.length * root.view.columnSpacing;
+ return 0.16 * parentWidthExclusingSpacing
+ }
+
+ delegate: Item {
+ id: visibilityContainer
+
+ implicitWidth: visibilityRow.implicitWidth
+ implicitHeight: visibilityRow.implicitHeight
+
+ visible: !visibilityLabel.isEmpty
+
+ readonly property var iconAndText: {
+ switch (score.cloudVisibility ?? 0) {
+ case CloudVisibility.Private:
+ return { "iconCode": IconCode.LOCK_CLOSED, "text": qsTrc("project/cloud", "Private") }
+ case CloudVisibility.Unlisted:
+ return { "iconCode": IconCode.LOCK_OPEN, "text": qsTrc("project/cloud", "Unlisted") }
+ case CloudVisibility.Public:
+ return { "iconCode": IconCode.GLOBE, "text": qsTrc("project/cloud", "Public") }
+ }
+ return { "iconCode": IconCode.NONE, "text": "" }
+ }
+
+ NavigationFocusBorder {
+ navigationCtrl: NavigationControl {
+ name: "VisibilityLabel"
+ panel: navigationPanel
+ row: navigationRow
+ column: navigationColumnStart
+ enabled: visibilityContainer.visible && visibilityContainer.enabled && !visibilityLabel.isEmpty
+ accessible.name: visibilityColumn.header + ": " + visibilityContainer.iconAndText.text
+ accessible.role: MUAccessible.StaticText
+
+ onActiveChanged: {
+ if (active) {
+ listItem.scrollIntoView()
+ }
+ }
+ }
+
+ anchors.margins: -radius
+ radius: 2 + border.width
+ }
+
+ RowLayout {
+ id: visibilityRow
+ spacing: 8
+
+ StyledIconLabel {
+ iconCode: visibilityContainer.iconAndText.iconCode
+ }
+
+ StyledTextLabel {
+ id: visibilityLabel
+ Layout.fillWidth: true
+
+ text: visibilityContainer.iconAndText.text
+
+ font: ui.theme.largeBodyFont
+ horizontalAlignment: Text.AlignLeft
+ }
+ }
+ }
+ },
+
+ ScoresListView.ColumnItem {
+ id: modifiedColumn
+
+ //: Stands for "Last time that this score was modified".
+ //: Used as the header of this column in the scores list.
+ header: qsTrc("project", "Modified")
+
+ width: function(parentWidth) {
+ let parentWidthExclusingSpacing = parentWidth - root.columns.length * root.view.columnSpacing;
+ return 0.16 * parentWidthExclusingSpacing
+ }
+
+ delegate: StyledTextLabel {
+ id: modifiedLabel
+ text: score.timeSinceModified ?? ""
+
+ font.capitalization: Font.AllUppercase
+ horizontalAlignment: Text.AlignLeft
+
+ NavigationFocusBorder {
+ navigationCtrl: NavigationControl {
+ name: "ModifiedLabel"
+ panel: navigationPanel
+ row: navigationRow
+ column: navigationColumnStart
+ enabled: modifiedLabel.visible && modifiedLabel.enabled && !modifiedLabel.isEmpty
+ accessible.name: modifiedColumn.header + ": " + modifiedLabel.text
+ accessible.role: MUAccessible.StaticText
+
+ onActiveChanged: {
+ if (active) {
+ listItem.scrollIntoView()
+ }
+ }
+ }
+
+ anchors.margins: -radius
+ radius: 2 + border.width
+ }
+ }
+ },
+
+ ScoresListView.ColumnItem {
+ id: sizeColumn
+ header: qsTrc("global", "Size", "file size")
+
+ width: function(parentWidth) {
+ let parentWidthExclusingSpacing = parentWidth - root.columns.length * root.view.columnSpacing;
+ return 0.13 * parentWidthExclusingSpacing
+ }
+
+ delegate: StyledTextLabel {
+ id: sizeLabel
+ text: Boolean(score.fileSize) ? score.fileSize : "-"
+
+ font: ui.theme.largeBodyFont
+ horizontalAlignment: Text.AlignLeft
+
+ NavigationFocusBorder {
+ navigationCtrl: NavigationControl {
+ name: "SizeLabel"
+ panel: navigationPanel
+ row: navigationRow
+ column: navigationColumnStart
+ enabled: sizeLabel.visible && sizeLabel.enabled && !sizeLabel.isEmpty
+ accessible.name: sizeColumn.header + ": " + (Boolean(score.fileSize) ? score.fileSize : qsTrc("global", "Unknown"))
+ accessible.role: MUAccessible.StaticText
+
+ onActiveChanged: {
+ if (active) {
+ listItem.scrollIntoView()
+ }
+ }
+ }
+
+ anchors.margins: -radius
+ radius: 2 + border.width
+ }
+ }
+ },
+
+ ScoresListView.ColumnItem {
+ id: viewsColumn
+
+ //: Stands for "The number of times this score was viewed on MuseScore.com".
+ //: Used as the header of this column in the scores list.
+ header: qsTrc("project", "Views", "number of views")
+
+ width: function(parentWidth) {
+ let parentWidthExclusingSpacing = parentWidth - root.columns.length * root.view.columnSpacing;
+ return Math.max(0.08 * parentWidthExclusingSpacing, 76)
+ }
+
+ delegate: Item {
+ id: viewsContainer
+
+ implicitWidth: viewsRow.implicitWidth
+ implicitHeight: viewsRow.implicitHeight
+
+ visible: !viewsLabel.isEmpty
+
+ NavigationFocusBorder {
+ navigationCtrl: NavigationControl {
+ name: "ViewsLabel"
+ panel: navigationPanel
+ row: navigationRow
+ column: navigationColumnStart
+ enabled: viewsContainer.visible && viewsContainer.enabled
+ accessible.name: viewsColumn.header + ": " + viewsLabel.text
+ accessible.role: MUAccessible.StaticText
+
+ onActiveChanged: {
+ if (active) {
+ listItem.scrollIntoView()
+ }
+ }
+ }
+
+ anchors.margins: -radius
+ radius: 2 + border.width
+ }
+
+ RowLayout {
+ id: viewsRow
+ spacing: 8
+
+ StyledIconLabel {
+ iconCode: IconCode.EYE_OPEN
+ }
+
+ StyledTextLabel {
+ id: viewsLabel
+ Layout.fillWidth: true
+
+ text: score.cloudViewCount ?? ""
+
+ font: ui.theme.largeBodyFont
+ horizontalAlignment: Text.AlignLeft
+ }
+ }
+ }
+ }
+ ]
+
+ view.footer: root.model.state === CloudScoresModel.Loading
+ ? busyIndicatorComp : null
+
+ Component {
+ id: busyIndicatorComp
+
+ Item {
+ width: ListView.view ? ListView.view.width : 0
+ height: root.view.rowHeight
+
+ StyledBusyIndicator {
+ id: indicator
+
+ anchors.centerIn: parent
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresView.qml b/src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresView.qml
new file mode 100644
index 0000000000000..7bb59874c10ae
--- /dev/null
+++ b/src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresView.qml
@@ -0,0 +1,221 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-Studio-CLA-applies
+ *
+ * MuseScore Studio
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2021 MuseScore Limited 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 .
+ */
+
+import QtQuick
+
+import Muse.Ui
+import Muse.UiComponents
+import Muse.Cloud
+import MuseScore.Project
+
+ScoresView {
+ id: root
+
+ CloudScoresModel {
+ id: cloudScoresModel
+ }
+
+ Component.onCompleted: {
+ cloudScoresModel.load()
+ }
+
+ function refresh() {
+ cloudScoresModel.reload()
+ }
+
+ sourceComponent: {
+ switch (cloudScoresModel.state) {
+ case CloudScoresModel.NotSignedIn:
+ return notSignedInComp
+ case CloudScoresModel.Error:
+ return errorComp
+ case CloudScoresModel.Fine:
+ case CloudScoresModel.Loading:
+ break;
+ }
+
+ if (cloudScoresModel.rowCount == 0 && !cloudScoresModel.hasMore && cloudScoresModel.state != CloudScoresModel.Loading) {
+ return emptyComp
+ }
+
+ return root.viewType === ScoresPageModel.List ? listComp : gridComp
+ }
+
+ Component {
+ id: gridComp
+
+ CloudScoresGridView {
+ anchors.fill: parent
+
+ model: cloudScoresModel
+ searchText: root.searchText
+
+ backgroundColor: root.backgroundColor
+ sideMargin: root.sideMargin
+
+ navigation.section: root.navigationSection
+ navigation.order: root.navigationOrder
+
+ onCreateNewScoreRequested: {
+ root.createNewScoreRequested()
+ }
+
+ onOpenScoreRequested: function(scorePath, displayName) {
+ root.openScoreRequested(scorePath, displayName)
+ }
+ }
+ }
+
+ Component {
+ id: listComp
+
+ CloudScoresListView {
+ anchors.fill: parent
+
+ model: cloudScoresModel
+ searchText: root.searchText
+
+ backgroundColor: root.backgroundColor
+ sideMargin: root.sideMargin
+
+ navigation.section: root.navigationSection
+ navigation.order: root.navigationOrder
+
+ onCreateNewScoreRequested: {
+ root.createNewScoreRequested()
+ }
+
+ onOpenScoreRequested: function(scorePath, displayName) {
+ root.openScoreRequested(scorePath, displayName)
+ }
+ }
+ }
+
+ Component {
+ id: emptyComp
+
+ Item {
+ anchors.fill: parent
+
+ Message {
+ anchors.top: parent.top
+ anchors.topMargin: Math.max(parent.height / 3 - height / 2, 0)
+ anchors.left: parent.left
+ anchors.leftMargin: root.sideMargin
+ anchors.right: parent.right
+ anchors.rightMargin: root.sideMargin
+
+ title: qsTrc("project", "You don’t have any online scores yet")
+ body: qsTrc("project", "Scores will appear here when you save a file to the cloud, or publish a score on MuseScore.com.").arg("https://musescore.com")
+ }
+ }
+ }
+
+ Component {
+ id: notSignedInComp
+
+ Item {
+ anchors.fill: parent
+
+ Column {
+ anchors.top: parent.top
+ anchors.topMargin: Math.max(parent.height / 3 - height / 2, 0)
+ anchors.left: parent.left
+ anchors.leftMargin: root.sideMargin
+ anchors.right: parent.right
+ anchors.rightMargin: root.sideMargin
+
+ spacing: 32
+
+ Message {
+ width: parent.width
+
+ title: qsTrc("project", "You are not signed in")
+ body: qsTrc("project", "Log in or create a new account on MuseScore.com to view online scores.").arg("https://musescore.com")
+ }
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: implicitWidth
+ spacing: 12
+
+ MuseScoreComAuthorizationModel {
+ id: authorizationModel
+ }
+
+ Component.onCompleted: {
+ authorizationModel.load()
+ }
+
+ NavigationPanel {
+ id: navPanel
+ name: "SignInButtons"
+ section: root.navigationSection
+ order: root.navigationOrder
+ direction: NavigationPanel.Horizontal
+ accessible.name: qsTrc("cloud", "Sign in buttons")
+ }
+
+ FlatButton {
+ navigation.panel: navPanel
+ navigation.order: 1
+
+ text: qsTrc("cloud", "Create account")
+ onClicked: {
+ authorizationModel.createAccount()
+ }
+ }
+
+ FlatButton {
+ navigation.panel: navPanel
+ navigation.order: 2
+
+ text: qsTrc("cloud", "Sign in")
+ onClicked: {
+ authorizationModel.signIn()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Component {
+ id: errorComp
+
+ Item {
+ anchors.fill: parent
+
+ Message {
+ anchors.top: parent.top
+ anchors.topMargin: Math.max(parent.height / 3 - height / 2, 0)
+ anchors.left: parent.left
+ anchors.leftMargin: root.sideMargin
+ anchors.right: parent.right
+ anchors.rightMargin: root.sideMargin
+
+ title: qsTrc("project", "Unable to load online scores")
+ body: qsTrc("global", "Please check your internet connection or try again later.")
+ }
+ }
+ }
+}
diff --git a/src/project/qml/MuseScore/Project/ScoresGridView.qml b/src/project/qml/MuseScore/Project/internal/ScoresPage/ScoresGridView.qml
similarity index 99%
rename from src/project/qml/MuseScore/Project/ScoresGridView.qml
rename to src/project/qml/MuseScore/Project/internal/ScoresPage/ScoresGridView.qml
index df7ce92b9c67a..84c0dcbb1fffd 100644
--- a/src/project/qml/MuseScore/Project/ScoresGridView.qml
+++ b/src/project/qml/MuseScore/Project/internal/ScoresPage/ScoresGridView.qml
@@ -26,8 +26,6 @@ import Muse.Ui
import Muse.UiComponents
import MuseScore.Project
-import "internal/ScoresPage"
-
Item {
id: root
diff --git a/src/project/qml/MuseScore/Project/ScoresListView.qml b/src/project/qml/MuseScore/Project/internal/ScoresPage/ScoresListView.qml
similarity index 99%
rename from src/project/qml/MuseScore/Project/ScoresListView.qml
rename to src/project/qml/MuseScore/Project/internal/ScoresPage/ScoresListView.qml
index 88e120280d957..17d847d000e02 100644
--- a/src/project/qml/MuseScore/Project/ScoresListView.qml
+++ b/src/project/qml/MuseScore/Project/internal/ScoresPage/ScoresListView.qml
@@ -27,8 +27,6 @@ import Muse.Ui
import Muse.UiComponents
import MuseScore.Project
-import "internal/ScoresPage"
-
Item {
id: root
diff --git a/src/project/qml/MuseScore/Project/ScoresView.qml b/src/project/qml/MuseScore/Project/internal/ScoresPage/ScoresView.qml
similarity index 100%
rename from src/project/qml/MuseScore/Project/ScoresView.qml
rename to src/project/qml/MuseScore/Project/internal/ScoresPage/ScoresView.qml