Changeset View
Standalone View
kded/qml/OsdSelector.qml
Show All 22 Lines | |||||
23 | import org.kde.plasma.extras 2.0 as PlasmaExtras | 23 | import org.kde.plasma.extras 2.0 as PlasmaExtras | ||
24 | 24 | | |||
25 | import org.kde.KScreen 1.0 | 25 | import org.kde.KScreen 1.0 | ||
26 | 26 | | |||
27 | PlasmaCore.Dialog { | 27 | PlasmaCore.Dialog { | ||
28 | id: root | 28 | id: root | ||
29 | location: PlasmaCore.Types.Floating | 29 | location: PlasmaCore.Types.Floating | ||
30 | type: PlasmaCore.Dialog.Normal | 30 | type: PlasmaCore.Dialog.Normal | ||
31 | visible: true | | |||
32 | property string infoText | 31 | property string infoText | ||
33 | 32 | | |||
34 | signal clicked(int actionId) | 33 | signal clicked(int actionId) | ||
35 | 34 | | |||
36 | mainItem: Item { | 35 | mainItem: Item { | ||
37 | height: Math.min(units.gridUnit * 15, Screen.desktopAvailableHeight / 5) | 36 | height: Math.min(units.gridUnit * 15, Screen.desktopAvailableHeight / 5) | ||
38 | width: buttonRow.width | 37 | width: buttonRow.width | ||
39 | 38 | | |||
40 | PlasmaComponents.ButtonRow { | 39 | PlasmaComponents.ButtonRow { | ||
41 | id: buttonRow | 40 | id: buttonRow | ||
42 | exclusive: false | 41 | exclusive: true | ||
43 | 42 | | |||
44 | height: parent.height - label.height - ((units.smallSpacing/2) * 3) | 43 | height: parent.height - label.height - ((units.smallSpacing/2) * 3) | ||
45 | width: (actionRepeater.count * height) + ((actionRepeater.count - 1) * buttonRow.spacing); | 44 | width: (actionRepeater.count * height) + ((actionRepeater.count - 1) * buttonRow.spacing); | ||
46 | 45 | | |||
47 | Repeater { | 46 | Repeater { | ||
48 | id: actionRepeater | 47 | id: actionRepeater | ||
48 | property int currentIndex: 0 | ||||
49 | model: [ | 49 | model: [ | ||
50 | { | 50 | { | ||
51 | iconSource: "osd-shutd-laptop", | 51 | iconSource: "osd-shutd-laptop", | ||
52 | label: i18n("Switch to external screen"), | 52 | label: i18n("Switch to external screen"), | ||
53 | action: OsdAction.SwitchToExternal | 53 | action: OsdAction.SwitchToExternal | ||
54 | }, | 54 | }, | ||
55 | { | 55 | { | ||
56 | iconSource: "osd-shutd-screen", | 56 | iconSource: "osd-shutd-screen", | ||
Show All 17 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 | actionRepeater.currentIndex = index | ||||
94 | } | ||||
95 | | ||||
96 | onClicked: root.clicked(action) | ||||
97 | activeFocusOnTab: true | ||||
92 | 98 | | |||
93 | onClicked: root.clicked(modelData.action) | 99 | // use checked only indirectly, since its binding will break | ||
100 | property bool current: index == actionRepeater.currentIndex | ||||
101 | onCurrentChanged: { | ||||
102 | if (current) { | ||||
103 | checked = true | ||||
104 | root.infoText = modelData.label | ||||
105 | forceActiveFocus() | ||||
106 | } else { | ||||
107 | checked = false | ||||
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… | |||||
108 | } | ||||
109 | } | ||||
110 | onActiveFocusChanged: { | ||||
111 | if (activeFocus) { | ||||
112 | actionRepeater.currentIndex = index | ||||
113 | } | ||||
114 | } | ||||
94 | } | 115 | } | ||
95 | } | 116 | } | ||
96 | } | 117 | } | ||
97 | 118 | | |||
98 | PlasmaExtras.Heading { | 119 | PlasmaExtras.Heading { | ||
99 | id: label | 120 | id: label | ||
100 | anchors { | 121 | anchors { | ||
101 | bottom: parent.bottom | 122 | bottom: parent.bottom | ||
102 | left: parent.left | 123 | left: parent.left | ||
103 | right: parent.right | 124 | right: parent.right | ||
104 | margins: Math.floor(units.smallSpacing / 2) | 125 | margins: Math.floor(units.smallSpacing / 2) | ||
105 | } | 126 | } | ||
106 | 127 | | |||
107 | text: root.infoText | 128 | text: root.infoText | ||
108 | horizontalAlignment: Text.AlignHCenter | 129 | horizontalAlignment: Text.AlignHCenter | ||
109 | wrapMode: Text.WordWrap | 130 | wrapMode: Text.WordWrap | ||
110 | maximumLineCount: 2 | 131 | maximumLineCount: 2 | ||
111 | elide: Text.ElideLeft | 132 | elide: Text.ElideLeft | ||
112 | minimumPointSize: theme.defaultFont.pointSize | 133 | minimumPointSize: theme.defaultFont.pointSize | ||
113 | fontSizeMode: Text.HorizontalFit | 134 | fontSizeMode: Text.HorizontalFit | ||
114 | } | 135 | } | ||
115 | 136 | | |||
116 | Component.onCompleted: print("OsdSelector loaded..."); | 137 | Component.onCompleted: print("OsdSelector loaded..."); | ||
138 | | ||||
139 | function next() { | ||||
140 | var index = actionRepeater.currentIndex + 1 | ||||
141 | if (index >= actionRepeater.count) { | ||||
142 | index = 0 | ||||
143 | } | ||||
144 | actionRepeater.currentIndex = index | ||||
145 | } | ||||
146 | function previous() { | ||||
147 | var index = actionRepeater.currentIndex - 1 | ||||
148 | if (index < 0) { | ||||
149 | index = actionRepeater.count - 1 | ||||
150 | } | ||||
151 | actionRepeater.currentIndex = index | ||||
152 | } | ||||
153 | | ||||
117 | Keys.onEscapePressed: clicked("dialog-cancel") | 154 | Keys.onEscapePressed: clicked("dialog-cancel") | ||
155 | Keys.onPressed: { | ||||
broulik: Also do `Keys.onEnterPressed` so that enter on numpad works | |||||
156 | if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { | ||||
157 | event.accepted = true | ||||
158 | clicked(buttonRow.checkedButton.action) | ||||
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… | |||||
159 | return | ||||
160 | } | ||||
161 | if (event.key === Qt.Key_Right) { | ||||
162 | event.accepted = true | ||||
davidedmundson: why do you accept right, but not left? | |||||
163 | next() | ||||
164 | return | ||||
165 | } | ||||
166 | if (event.key === Qt.Key_Left) { | ||||
167 | previous() | ||||
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. | |||||
168 | return | ||||
169 | } | ||||
170 | } | ||||
118 | } | 171 | } | ||
119 | } | 172 | } | ||
120 | 173 | | |||
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… |
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.