Changeset View
Standalone View
kded/qml/OsdSelector.qml
Show All 33 Lines | 27 | PlasmaCore.Dialog { | |||
---|---|---|---|---|---|
34 | signal clicked(int actionId) | 34 | signal clicked(int actionId) | ||
35 | 35 | | |||
36 | mainItem: Item { | 36 | mainItem: Item { | ||
37 | height: Math.min(units.gridUnit * 15, Screen.desktopAvailableHeight / 5) | 37 | height: Math.min(units.gridUnit * 15, Screen.desktopAvailableHeight / 5) | ||
38 | width: buttonRow.width | 38 | width: buttonRow.width | ||
39 | 39 | | |||
40 | PlasmaComponents.ButtonRow { | 40 | PlasmaComponents.ButtonRow { | ||
41 | id: buttonRow | 41 | id: buttonRow | ||
42 | exclusive: false | 42 | exclusive: true | ||
43 | 43 | | |||
44 | height: parent.height - label.height - ((units.smallSpacing/2) * 3) | 44 | height: parent.height - label.height - ((units.smallSpacing/2) * 3) | ||
45 | width: (actionRepeater.count * height) + ((actionRepeater.count - 1) * buttonRow.spacing); | 45 | width: (actionRepeater.count * height) + ((actionRepeater.count - 1) * buttonRow.spacing); | ||
46 | 46 | | |||
47 | Repeater { | 47 | Repeater { | ||
48 | id: actionRepeater | 48 | id: actionRepeater | ||
49 | model: [ | 49 | model: [ | ||
50 | { | 50 | { | ||
Show All 23 Lines | |||||
74 | }, | 74 | }, | ||
75 | { | 75 | { | ||
76 | iconSource: "dialog-cancel", | 76 | iconSource: "dialog-cancel", | ||
77 | label: i18n("Leave unchanged"), | 77 | label: i18n("Leave unchanged"), | ||
78 | action: OsdAction.NoAction | 78 | action: OsdAction.NoAction | ||
79 | } | 79 | } | ||
80 | ] | 80 | ] | ||
81 | delegate: PlasmaComponents.Button { | 81 | delegate: PlasmaComponents.Button { | ||
82 | property var action: modelData.action | ||||
82 | PlasmaCore.IconItem { | 83 | PlasmaCore.IconItem { | ||
83 | source: modelData.iconSource | 84 | source: modelData.iconSource | ||
84 | height: buttonRow.height - ((units.smallSpacing / 2) * 3) | 85 | height: buttonRow.height - ((units.smallSpacing / 2) * 3) | ||
85 | width: height | 86 | width: height | ||
86 | anchors.centerIn: parent | 87 | anchors.centerIn: parent | ||
87 | } | 88 | } | ||
88 | height: parent.height | 89 | height: parent.height | ||
89 | width: height | 90 | width: height | ||
90 | 91 | | |||
91 | onHoveredChanged: root.infoText = (hovered ? modelData.label : "") | 92 | onHoveredChanged: { | ||
93 | if (hovered) { | ||||
94 | checked = true | ||||
95 | } | ||||
96 | } | ||||
92 | 97 | | |||
93 | onClicked: root.clicked(modelData.action) | 98 | onClicked: root.clicked(action) | ||
99 | activeFocusOnTab: true | ||||
100 | checked: activeFocus | ||||
101 | onCheckedChanged: { | ||||
102 | if (checked) { | ||||
103 | root.infoText = modelData.label | ||||
104 | } | ||||
105 | } | ||||
106 | Component.onCompleted: { | ||||
davidedmundson: Given we're doing this manually, we should drop the ButtonRow which is also meddling with… | |||||
Row does result in different spacing. I wonder if it's better to leave the ButtonRow without the exclusive set, or replace it with row and add spacing. On the other hand, it's just one line. gladhorn: Row does result in different spacing. I wonder if it's better to leave the ButtonRow without… | |||||
107 | // arbitrary and not very sensible default, focus on first button | ||||
108 | if (index == 0) { | ||||
109 | forceActiveFocus() | ||||
110 | } | ||||
111 | } | ||||
94 | } | 112 | } | ||
95 | } | 113 | } | ||
96 | } | 114 | } | ||
97 | 115 | | |||
98 | PlasmaExtras.Heading { | 116 | PlasmaExtras.Heading { | ||
99 | id: label | 117 | id: label | ||
100 | anchors { | 118 | anchors { | ||
101 | bottom: parent.bottom | 119 | bottom: parent.bottom | ||
102 | left: parent.left | 120 | left: parent.left | ||
103 | right: parent.right | 121 | right: parent.right | ||
104 | margins: Math.floor(units.smallSpacing / 2) | 122 | margins: Math.floor(units.smallSpacing / 2) | ||
105 | } | 123 | } | ||
106 | 124 | | |||
107 | text: root.infoText | 125 | text: root.infoText | ||
108 | horizontalAlignment: Text.AlignHCenter | 126 | horizontalAlignment: Text.AlignHCenter | ||
109 | wrapMode: Text.WordWrap | 127 | wrapMode: Text.WordWrap | ||
110 | maximumLineCount: 2 | 128 | maximumLineCount: 2 | ||
111 | elide: Text.ElideLeft | 129 | elide: Text.ElideLeft | ||
112 | minimumPointSize: theme.defaultFont.pointSize | 130 | minimumPointSize: theme.defaultFont.pointSize | ||
113 | fontSizeMode: Text.HorizontalFit | 131 | fontSizeMode: Text.HorizontalFit | ||
114 | } | 132 | } | ||
115 | 133 | | |||
116 | Component.onCompleted: print("OsdSelector loaded..."); | 134 | Component.onCompleted: print("OsdSelector loaded..."); | ||
117 | Keys.onEscapePressed: clicked("dialog-cancel") | 135 | Keys.onEscapePressed: clicked("dialog-cancel") | ||
136 | Keys.onReturnPressed: { | ||||
broulik: Also do `Keys.onEnterPressed` so that enter on numpad works | |||||
137 | clicked(buttonRow.checkedButton.action) | ||||
138 | } | ||||
139 | Keys.onPressed: { | ||||
I'd like to hear suggestions how to do this in a nicer fashion, iterating over the children and checking if they are buttons and otherwise skipping them feels pretty ugly. gladhorn: I'd like to hear suggestions how to do this in a nicer fashion, iterating over the children and… | |||||
Personally I would add a property currentIndex in the repeater, have Keys.right/left manipulate that and then have the delegates compare that to their index. davidedmundson: Personally I would add a property currentIndex in the repeater, have Keys.right/left… | |||||
140 | if (event.key === Qt.Key_Right || event.key === Qt.Key_Left) { | ||||
141 | var i = 0 | ||||
142 | for (i = 0; i < buttonRow.children.length; i = i+1) { | ||||
143 | if (buttonRow.children[i].checked) { | ||||
davidedmundson: why do you accept right, but not left? | |||||
144 | break; | ||||
145 | } | ||||
146 | } | ||||
147 | // check for checked property, the repeater is also a child and must be skipped | ||||
148 | if (event.key === Qt.Key_Left) { | ||||
Make sure you take into account right-to-left languages (not sure if the layout mirrors then but it should, check by running the app with -reverse argument) broulik: Make sure you take into account right-to-left languages (not sure if the layout mirrors then… | |||||
gladhorn: Currently -reverse has no effect on the whole thing afaict. | |||||
149 | do { | ||||
150 | i = i - 1 | ||||
151 | if (i < 0) { | ||||
152 | i = buttonRow.children.length - 1 | ||||
153 | } | ||||
154 | } while (!buttonRow.children[i] || !buttonRow.children[i].hasOwnProperty("checked")) | ||||
155 | | ||||
156 | } | ||||
157 | if (event.key === Qt.Key_Right) { | ||||
158 | do { | ||||
159 | i = i + 1 | ||||
160 | if (i >= buttonRow.children.length) { | ||||
161 | i = 0 | ||||
162 | } | ||||
163 | } while (!buttonRow.children[i] || !buttonRow.children[i].hasOwnProperty("checked")) | ||||
164 | } | ||||
165 | buttonRow.children[i].checked = true | ||||
This breaks the checked: activeFocus binding in the delegate, which means use of tab after nav keys gets out of sync. davidedmundson: This breaks the checked: activeFocus binding in the delegate, which means use of tab after nav… | |||||
166 | return | ||||
167 | } | ||||
168 | } | ||||
118 | } | 169 | } | ||
119 | } | 170 | } | ||
120 | 171 | |
Given we're doing this manually, we should drop the ButtonRow which is also meddling with what's checked or not.
Row should be a drop in replacement.