Implemented accessibility for value list
This commit is contained in:
parent
035fbc5c9b
commit
2175f5ed25
9 changed files with 169 additions and 25 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ Item {
|
|||
|
||||
model: mappingsModel
|
||||
|
||||
onDoubleClicked: {
|
||||
onHandleItem: {
|
||||
editMappingDialog.startEditCurrentAction()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -51,7 +51,7 @@ ValueList {
|
|||
]
|
||||
}
|
||||
|
||||
onDoubleClicked: {
|
||||
onHandleItem: {
|
||||
root.startEditCurrentShortcutRequested()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue