diff --git a/src/appshell/qml/Preferences/internal/AccentColorsSection.qml b/src/appshell/qml/Preferences/internal/AccentColorsSection.qml index 64c9834a6c..c6398aef76 100644 --- a/src/appshell/qml/Preferences/internal/AccentColorsSection.qml +++ b/src/appshell/qml/Preferences/internal/AccentColorsSection.qml @@ -74,9 +74,12 @@ Row { checked: view.currentIndex === model.index + property color accentColor: modelData + navigation.name: "AccentColourButton" navigation.panel: root.navigation navigation.column: model.index + navigation.accessible.name: Utils.colorToString(accentColor) onClicked: { root.accentColorChangeRequested(model.index) @@ -104,7 +107,7 @@ Row { border.color: ui.theme.strokeColor border.width: 1 - color: modelData + color: button.accentColor } } diff --git a/src/framework/shortcuts/qml/MuseScore/Shortcuts/MidiDeviceMappingPage.qml b/src/framework/shortcuts/qml/MuseScore/Shortcuts/MidiDeviceMappingPage.qml index 42be6b9cfa..0c838dc736 100644 --- a/src/framework/shortcuts/qml/MuseScore/Shortcuts/MidiDeviceMappingPage.qml +++ b/src/framework/shortcuts/qml/MuseScore/Shortcuts/MidiDeviceMappingPage.qml @@ -89,7 +89,7 @@ Item { model: mappingsModel - onDoubleClicked: { + onHandleItem: { editMappingDialog.startEditCurrentAction() } } diff --git a/src/framework/shortcuts/qml/MuseScore/Shortcuts/ShortcutsPage.qml b/src/framework/shortcuts/qml/MuseScore/Shortcuts/ShortcutsPage.qml index e715a92197..fc8839a277 100644 --- a/src/framework/shortcuts/qml/MuseScore/Shortcuts/ShortcutsPage.qml +++ b/src/framework/shortcuts/qml/MuseScore/Shortcuts/ShortcutsPage.qml @@ -109,6 +109,9 @@ Item { sourceModel: shortcutsModel searchText: topPanel.searchText + navigationSection: root.navigationSection + navigationOrderStart: root.navigationOrderStart + 2 + onStartEditCurrentShortcutRequested: { editShortcutDialog.startEditCurrentShortcut() } @@ -123,7 +126,8 @@ Item { buttonWidth: prv.buttonWidth navigation.section: root.navigationSection - navigation.order: root.navigationOrderStart + 3 + //! NOTE: 4 because ShortcutsList have two panels(header and content) + navigation.order: root.navigationOrderStart + 4 onImportShortcutsFromFileRequested: { shortcutsModel.importShortcutsFromFile() diff --git a/src/framework/shortcuts/qml/MuseScore/Shortcuts/internal/ShortcutsList.qml b/src/framework/shortcuts/qml/MuseScore/Shortcuts/internal/ShortcutsList.qml index 7a90b40053..0f9c0f285a 100644 --- a/src/framework/shortcuts/qml/MuseScore/Shortcuts/internal/ShortcutsList.qml +++ b/src/framework/shortcuts/qml/MuseScore/Shortcuts/internal/ShortcutsList.qml @@ -51,7 +51,7 @@ ValueList { ] } - onDoubleClicked: { + onHandleItem: { root.startEditCurrentShortcutRequested() } } diff --git a/src/framework/uicomponents/qml/MuseScore/UiComponents/ColorPicker.qml b/src/framework/uicomponents/qml/MuseScore/UiComponents/ColorPicker.qml index 41aa9ec5f3..1c23cd18d5 100644 --- a/src/framework/uicomponents/qml/MuseScore/UiComponents/ColorPicker.qml +++ b/src/framework/uicomponents/qml/MuseScore/UiComponents/ColorPicker.qml @@ -24,6 +24,8 @@ import QtQuick.Dialogs 1.2 import MuseScore.Ui 1.0 +import "Utils.js" as Utils + Rectangle { id: root @@ -50,6 +52,9 @@ Rectangle { id: navCtrl name: root.objectName != "" ? root.objectName : "ColorPicker" enabled: root.enabled && root.visible + accessible.role: MUAccessible.Button + accessible.name: Utils.colorToString(root.color) + onTriggered: colorDialog.open() } diff --git a/src/framework/uicomponents/qml/MuseScore/UiComponents/Utils.js b/src/framework/uicomponents/qml/MuseScore/UiComponents/Utils.js index aef651ace9..54fdd4a66c 100644 --- a/src/framework/uicomponents/qml/MuseScore/UiComponents/Utils.js +++ b/src/framework/uicomponents/qml/MuseScore/UiComponents/Utils.js @@ -24,3 +24,17 @@ function colorWithAlpha(color, alpha) { return Qt.rgba(color.r, color.g, color.b, alpha) } + +function colorToString(color) { + var percentName = qsTrc("uicomponents", "percent") + var colorValueToPercent = function(value) { + return Math.floor(value * 100) + } + + var colorValueTemplate = "%1 %2 %3 " + var text = colorValueTemplate.arg(qsTrc("uicomponents", "Red")).arg(colorValueToPercent(color.r)).arg(percentName) + + colorValueTemplate.arg(qsTrc("uicomponents", "Green")).arg(colorValueToPercent(color.g)).arg(percentName) + + colorValueTemplate.arg(qsTrc("uicomponents", "Blue")).arg(colorValueToPercent(color.b)).arg(percentName) + + return text +} diff --git a/src/framework/uicomponents/qml/MuseScore/UiComponents/ValueList.qml b/src/framework/uicomponents/qml/MuseScore/UiComponents/ValueList.qml index 9b9b5cf9ae..fc122d1862 100644 --- a/src/framework/uicomponents/qml/MuseScore/UiComponents/ValueList.qml +++ b/src/framework/uicomponents/qml/MuseScore/UiComponents/ValueList.qml @@ -23,8 +23,8 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import MuseScore.UiComponents 1.0 import MuseScore.Ui 1.0 +import MuseScore.UiComponents 1.0 import "internal" @@ -46,7 +46,10 @@ Item { property alias hasSelection: selectionModel.hasSelection readonly property var selection: sortFilterProxyModel.mapSelectionToSource(selectionModel.selection) - signal doubleClicked(var index, var item) + property NavigationSection navigationSection: null + property int navigationOrderStart: 0 + + signal handleItem(var index, var item) QtObject { id: privateProperties @@ -110,6 +113,21 @@ Item { anchors.right: parent.right height: 38 + property NavigationPanel headerNavigation: NavigationPanel { + name: "ValueListHeaderPanel" + section: root.navigationSection + direction: NavigationPanel.Horizontal + order: root.navigationOrderStart + accessible.name: qsTrc("uicomponents", "Value list header panel") + enabled: root.visible + + onActiveChanged: { + if (active) { + root.forceActiveFocus() + } + } + } + ValueListHeaderItem { Layout.fillHeight: true Layout.fillWidth: true @@ -120,6 +138,9 @@ Item { isSorterEnabled: keySorter.enabled sortOrder: keySorter.sortOrder + navigation.panel: header.headerNavigation + navigation.order: 1 + onClicked: { privateProperties.toggleSorter(keySorter) privateProperties.setSorterEnabled(valueSorter, false) @@ -137,6 +158,9 @@ Item { isSorterEnabled: valueSorter.enabled sortOrder: valueSorter.sortOrder + navigation.panel: header.headerNavigation + navigation.order: 2 + onClicked: { privateProperties.toggleSorter(valueSorter) privateProperties.setSorterEnabled(keySorter, false) @@ -160,35 +184,77 @@ Item { clip: true boundsBehavior: Flickable.StopAtBounds + property NavigationPanel navigation: NavigationPanel { + name: "ValueListPanel" + section: root.navigationSection + direction: NavigationPanel.Both + order: root.navigationOrderStart + 1 + accessible.name: qsTrc("uicomponents", "Value list panel") + enabled: root.visible + + onActiveChanged: { + if (active) { + root.forceActiveFocus() + } + } + } + ScrollBar.vertical: StyledScrollBar { anchors.right: parent.right anchors.rightMargin: 8 } - delegate: ValueListItem { - item: model + delegate: Item { + //! NOTE: Added to prevent components clipping when navigating + width: view.width + height: listItem.height + ui.theme.navCtrlBorderWidth * 2 - property var modelIndex: sortFilterProxyModel.index(item.index, 0) + ValueListItem { + id: listItem - keyRoleName: root.keyRoleName - valueRoleName: root.valueRoleName - valueTypeRole: root.valueTypeRole - valueEnabledRoleName: root.valueEnabledRoleName - iconRoleName: root.iconRoleName + anchors.centerIn: parent + width: view.width - ui.theme.navCtrlBorderWidth * 2 - isSelected: selectionModel.hasSelection && selectionModel.isSelected(modelIndex) - readOnly: root.readOnly + navigation.enabled: true - spacing: privateProperties.spacing - sideMargin: privateProperties.sideMargin - valueItemWidth: privateProperties.valueItemWidth + item: model - onClicked: { - selectionModel.select(modelIndex) - } + property var modelIndex: sortFilterProxyModel.index(item.index, 0) - onDoubleClicked: { - root.doubleClicked(sortFilterProxyModel.mapToSource(modelIndex), item) + keyRoleName: root.keyRoleName + valueRoleName: root.valueRoleName + valueTypeRole: root.valueTypeRole + valueEnabledRoleName: root.valueEnabledRoleName + iconRoleName: root.iconRoleName + + isSelected: selectionModel.hasSelection && selectionModel.isSelected(modelIndex) + readOnly: root.readOnly + + spacing: privateProperties.spacing + sideMargin: privateProperties.sideMargin + valueItemWidth: privateProperties.valueItemWidth + + navigation.panel: view.navigation + navigation.row: item.index + navigation.column: 0 + + onClicked: { + selectionModel.select(modelIndex) + } + + onDoubleClicked: { + root.handleItem(sortFilterProxyModel.mapToSource(modelIndex), item) + } + + onNavigationTriggered: { + root.handleItem(sortFilterProxyModel.mapToSource(modelIndex), item) + } + + onFocusChanged: { + if (activeFocus) { + view.positionViewAtIndex(index, ListView.Contain) + } + } } } } diff --git a/src/framework/uicomponents/qml/MuseScore/UiComponents/internal/ValueListHeaderItem.qml b/src/framework/uicomponents/qml/MuseScore/UiComponents/internal/ValueListHeaderItem.qml index b7d45326a0..922c23549b 100644 --- a/src/framework/uicomponents/qml/MuseScore/UiComponents/internal/ValueListHeaderItem.qml +++ b/src/framework/uicomponents/qml/MuseScore/UiComponents/internal/ValueListHeaderItem.qml @@ -32,12 +32,39 @@ Item { property bool isSorterEnabled: false property int sortOrder: Qt.AscendingOrder + property alias navigation: navCtrl + signal clicked() + NavigationControl { + id: navCtrl + name: root.objectName !== "" ? root.objectName : "ValueListHeaderItem" + enabled: root.enabled && root.visible + + accessible.role: MUAccessible.Button + accessible.name: { + var text = root.headerTitle + if (root.isSorterEnabled) { + var sortOrderName = root.sortOrder === Qt.AscendingOrder ? qsTrc("uicomponents", "ascending") : qsTrc("uicomponents", "descending") + text += " " + qsTrc("uicomponents", "sort ") + sortOrderName + } else { + text += qsTrc("uicomponents", "sort default") + } + + return text + } + accessible.visualItem: root + + onTriggered: { + root.clicked() + } + } + Row { id: row anchors.fill: parent + spacing: root.spacing StyledTextLabel { @@ -62,6 +89,13 @@ Item { } } + NavigationFocusBorder { + anchors.leftMargin: -4 + anchors.rightMargin: -4 + + navigationCtrl: navCtrl + } + MouseArea { id: mouseArea diff --git a/src/framework/uicomponents/qml/MuseScore/UiComponents/internal/ValueListItem.qml b/src/framework/uicomponents/qml/MuseScore/UiComponents/internal/ValueListItem.qml index 51e363b406..c5c5ae09db 100644 --- a/src/framework/uicomponents/qml/MuseScore/UiComponents/internal/ValueListItem.qml +++ b/src/framework/uicomponents/qml/MuseScore/UiComponents/internal/ValueListItem.qml @@ -42,12 +42,13 @@ ListItemBlank { property real sideMargin: 0 property real valueItemWidth: 126 - width: ListView.view.width height: 34 normalStateColor: (index % 2 == 0) ? ui.theme.backgroundSecondaryColor : ui.theme.backgroundPrimaryColor + navigation.accessible.name: titleLabel.text + ": " + (Boolean(loader.item) ? loader.item.accessibleName : "") + QtObject { id: privateProperties @@ -90,6 +91,7 @@ ListItemBlank { } StyledTextLabel { + id: titleLabel text: root.item[keyRoleName] horizontalAlignment: Text.AlignLeft } @@ -110,6 +112,10 @@ ListItemBlank { onLoaded: { loader.item.val = loader.val + loader.item.navigation.panel = root.navigation.panel + loader.item.navigation.row = root.navigation.row + loader.item.navigation.column = 1 + if (privateProperties.isNumberComponent() && !root.readOnly) { if (Boolean(root.item.min)) { loader.item.minValue = root.item.min @@ -144,6 +150,8 @@ ListItemBlank { property string val signal changed(string newVal) + property string accessibleName: navigation.accessible.name + currentText: val onCurrentTextEdited: { @@ -160,6 +168,8 @@ ListItemBlank { property color val signal changed(color newVal) + property string accessibleName: navigation.accessible.name + color: val onNewColorSelected: { @@ -176,6 +186,8 @@ ListItemBlank { property int val signal changed(int newVal) + property string accessibleName: navigation.accessible.name + currentValue: val step: 1 @@ -195,6 +207,8 @@ ListItemBlank { property double val signal changed(double newVal) + property string accessibleName: navigation.accessible.name + currentValue: val step: 1.0 @@ -212,6 +226,8 @@ ListItemBlank { property bool val signal changed(bool newVal) + property string accessibleName: checked ? qsTrc("uicomponents", "checked") : qsTrc("uicomponents", "unchecked") + checked: val ? true : false onClicked: { boolControl.changed(!boolControl.checked) @@ -226,6 +242,8 @@ ListItemBlank { property var val signal changed(var stub) + property string accessibleName: text + text: val horizontalAlignment: Text.AlignLeft }