diff --git a/framework/cloud/qml/Muse/Cloud/CMakeLists.txt b/framework/cloud/qml/Muse/Cloud/CMakeLists.txt
index 3d6cb88687..46ee26c0ac 100644
--- a/framework/cloud/qml/Muse/Cloud/CMakeLists.txt
+++ b/framework/cloud/qml/Muse/Cloud/CMakeLists.txt
@@ -34,10 +34,7 @@ qt_add_qml_module(muse_cloud_qml
AccountAvatar.qml
AccountInfoButton.qml
AccountPage.qml
- CloudScoresView.qml
internal/CloudItem.qml
- internal/CloudScoresGridView.qml
- internal/CloudScoresListView.qml
internal/CloudsListView.qml
RequireAuthorizationDialog.qml
IMPORTS
diff --git a/framework/cloud/qml/Muse/Cloud/CloudScoresView.qml b/framework/cloud/qml/Muse/Cloud/CloudScoresView.qml
deleted file mode 100644
index 994335da78..0000000000
--- a/framework/cloud/qml/Muse/Cloud/CloudScoresView.qml
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * SPDX-License-Identifier: GPL-3.0-only
- * MuseScore-CLA-applies
- *
- * MuseScore
- * 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
-
-import "internal"
-
-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/framework/cloud/qml/Muse/Cloud/internal/CloudScoresGridView.qml b/framework/cloud/qml/Muse/Cloud/internal/CloudScoresGridView.qml
deleted file mode 100644
index 292b6b1e17..0000000000
--- a/framework/cloud/qml/Muse/Cloud/internal/CloudScoresGridView.qml
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * SPDX-License-Identifier: GPL-3.0-only
- * MuseScore-CLA-applies
- *
- * MuseScore
- * 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
- }
- }
- }
-}
diff --git a/framework/cloud/qml/Muse/Cloud/internal/CloudScoresListView.qml b/framework/cloud/qml/Muse/Cloud/internal/CloudScoresListView.qml
deleted file mode 100644
index 82959f6184..0000000000
--- a/framework/cloud/qml/Muse/Cloud/internal/CloudScoresListView.qml
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * SPDX-License-Identifier: GPL-3.0-only
- * MuseScore-CLA-applies
- *
- * MuseScore
- * 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
- 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
- }
- }
- }
-}
diff --git a/framework/stubs/cloud/qml/Muse/Cloud/CMakeLists.txt b/framework/stubs/cloud/qml/Muse/Cloud/CMakeLists.txt
index f5c809471f..ae97b67809 100644
--- a/framework/stubs/cloud/qml/Muse/Cloud/CMakeLists.txt
+++ b/framework/stubs/cloud/qml/Muse/Cloud/CMakeLists.txt
@@ -26,7 +26,6 @@ qt_add_qml_module(muse_cloud_qml
QML_FILES
AccountInfoButton.qml
AccountPage.qml
- CloudScoresView.qml
IMPORTS
TARGET muse_ui_qml
TARGET muse_uicomponents_qml
diff --git a/framework/stubs/cloud/qml/Muse/Cloud/CloudScoresView.qml b/framework/stubs/cloud/qml/Muse/Cloud/CloudScoresView.qml
deleted file mode 100644
index 0ad975ca90..0000000000
--- a/framework/stubs/cloud/qml/Muse/Cloud/CloudScoresView.qml
+++ /dev/null
@@ -1,28 +0,0 @@
-import QtQuick
-
-import Muse.Ui
-import Muse.UiComponents
-
-Rectangle {
- id: stub
-
- color: ui.theme.backgroundPrimaryColor
-
- property string searchText
-
- property int viewType
-
- property alias backgroundColor: stub.color
- property real sideMargin
-
- property NavigationSection navigationSection
- property int navigationOrder
-
- signal createNewScoreRequested()
- signal openScoreRequested(var scorePath, var displayName)
-
- StyledTextLabel {
- anchors.centerIn: parent
- text: "CloudScoresView Stub"
- }
-}