Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/project/qml/MuseScore/Project/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,23 @@ 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
NewScoreDialog.qml
ProjectPropertiesDialog.qml
ProjectUploadedDialog.qml
SaveToCloudDialog.qml
ScoresGridView.qml
ScoresListView.qml
ScoresPage.qml
ScoresView.qml
UploadProgressDialog.qml
RESOURCES
internal/Migration/migration.png
Expand All @@ -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
Expand Down
3 changes: 0 additions & 3 deletions src/project/qml/MuseScore/Project/ScoresPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.
*/
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()
}
Comment on lines +36 to +38
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add defensive guards for early grid geometry values.

Pagination currently assumes valid cellHeight/columns. Guarding these values avoids unstable desired-row updates during early layout.

Proposed patch
     Component.onCompleted: {
-        prv.updateDesiredRowCount()
+        Qt.callLater(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();
             }
         }
     }

+    Connections {
+        target: root.view
+        function onCellHeightChanged() {
+            if (root.view.cellHeight > 0 && root.view.columns > 0) {
+                prv.updateDesiredRowCount()
+            }
+        }
+        function onColumnsChanged() {
+            if (root.view.cellHeight > 0 && root.view.columns > 0) {
+                prv.updateDesiredRowCount()
+            }
+        }
+    }
+
     QtObject {
         id: prv
@@
         function updateDesiredRowCount() {
+            if (root.view.cellHeight <= 0 || root.view.columns <= 0) {
+                return
+            }
+
             if (updateDesiredRowCountScheduled) {
                 return
             }

Also applies to: 54-56, 67-87

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/project/qml/MuseScore/Project/internal/ScoresPage/CloudScoresGridView.qml`
around lines 36 - 38, Component.onCompleted currently calls
prv.updateDesiredRowCount() without guarding for early/invalid geometry (e.g.,
cellHeight <= 0 or columns <= 0), causing unstable pagination; update the
Component.onCompleted handler in CloudScoresGridView.qml (and the other similar
blocks around the 54-56 and 67-87 regions) to check that relevant layout metrics
(columns and cellHeight) are positive and finite before calling
prv.updateDesiredRowCount(), and in the callers inside the
resize/geometry-change logic ensure the same guards are applied so
updateDesiredRowCount() only runs when the grid has valid geometry.


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