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" - } -}