Changeset View
Changeset View
Standalone View
Standalone View
kcms/keyboard/tastenbrett/qml/main.qml
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | Copyright 2019 Harald Sitter <sitter@kde.org> | ||||
3 | | ||||
4 | This program is free software; you can redistribute it and/or | ||||
5 | modify it under the terms of the GNU General Public License as | ||||
6 | published by the Free Software Foundation; either version 2 of | ||||
7 | the License or (at your option) version 3 or any later version | ||||
8 | accepted by the membership of KDE e.V. (or its successor approved | ||||
9 | by the membership of KDE e.V.), which shall act as a proxy | ||||
10 | defined in Section 14 of version 3 of the license. | ||||
11 | | ||||
12 | This program is distributed in the hope that it will be useful, | ||||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
15 | GNU General Public License for more details. | ||||
16 | | ||||
17 | You should have received a copy of the GNU General Public License | ||||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
19 | */ | ||||
20 | | ||||
21 | import QtQuick 2.12 | ||||
22 | import QtQuick.Window 2.12 | ||||
23 | import QtQuick.Controls 2.5 | ||||
24 | | ||||
25 | import org.kde.tastenbrett.private 1.0 as XKB | ||||
26 | | ||||
27 | Window { | ||||
28 | id: window | ||||
29 | visible: false | ||||
30 | width: 1024 | ||||
31 | height: 768 | ||||
32 | | ||||
33 | SystemPalette { id: activePalette; colorGroup: SystemPalette.Active } | ||||
34 | SystemPalette { id: disabledPalette; colorGroup: SystemPalette.Disabled } | ||||
35 | | ||||
36 | function createDoodad(doodad, parent, properties) { | ||||
37 | var component = null | ||||
38 | if (doodad instanceof XKB.LogoDoodad) { | ||||
39 | component = doodadLogoComponent | ||||
40 | } else if (doodad instanceof XKB.IndicatorDoodad) { | ||||
41 | component = doodadIndicatorComponent | ||||
42 | } else if (doodad instanceof XKB.TextDoodad) { | ||||
43 | component = doodadTextComponent | ||||
44 | } else if (doodad instanceof XKB.ShapeDoodad) { | ||||
45 | component = doodadShapeComponent | ||||
46 | } | ||||
47 | if (component) { | ||||
48 | return component.createObject(parent, properties) | ||||
49 | } | ||||
50 | console.error("Unknown doodad type!", doodad) | ||||
51 | return null | ||||
52 | } | ||||
53 | | ||||
54 | Rectangle { | ||||
55 | anchors.fill: parent | ||||
56 | color: activePalette.window | ||||
57 | } | ||||
58 | | ||||
59 | Item { | ||||
60 | id: kbd | ||||
61 | width: window.width | ||||
62 | height: window.height | ||||
63 | | ||||
64 | // XKB geometries have a consistent coordinate system within a geometry | ||||
65 | // all children follow that system instead of QML. To easily convert | ||||
66 | // everything wholesale we'll employ a scale factor. | ||||
67 | property real childWidth: childrenRect.x + childrenRect.width | ||||
68 | property real childHeight: childrenRect.y + childrenRect.height | ||||
69 | // We preserve the ratio and as a result will need to scall either | ||||
70 | // with height or width, whichever has less space. | ||||
71 | scale: Math.min(width / childWidth, height / childHeight) | ||||
72 | transformOrigin: Item.TopLeft | ||||
73 | } | ||||
74 | | ||||
75 | Component { | ||||
76 | id: keyComponent | ||||
77 | | ||||
78 | // Interactable Key | ||||
79 | Key { | ||||
80 | id: root | ||||
81 | | ||||
82 | MouseArea { | ||||
83 | id: hoverArea | ||||
84 | anchors.fill: parent | ||||
85 | hoverEnabled: true | ||||
86 | } | ||||
87 | | ||||
88 | ToolTip { | ||||
89 | visible: hoverArea.containsMouse | ||||
90 | | ||||
91 | contentItem: Item { | ||||
92 | scale: kbd.scale * 3 // make keys easily redable at 2.5 times the regular size | ||||
93 | | ||||
94 | Key { | ||||
95 | id: keyItem | ||||
96 | key: root.key | ||||
97 | } | ||||
98 | } | ||||
99 | | ||||
100 | background: null | ||||
101 | } | ||||
102 | } | ||||
103 | } | ||||
104 | | ||||
105 | Component { | ||||
106 | id: doodadShapeComponent | ||||
107 | ShapeDoodad {} | ||||
108 | } | ||||
109 | | ||||
110 | Component { | ||||
111 | id: doodadIndicatorComponent | ||||
112 | IndicatorDoodad {} | ||||
113 | } | ||||
114 | | ||||
115 | Component { | ||||
116 | id: doodadTextComponent | ||||
117 | TextDoodad {} | ||||
118 | } | ||||
119 | | ||||
120 | Component { | ||||
121 | id: doodadLogoComponent | ||||
122 | ShapeDoodad { | ||||
123 | KeyCapLabel { | ||||
124 | anchors.centerIn: parent | ||||
125 | color: disabledPalette.buttonText | ||||
126 | text: doodad.logo_name | ||||
127 | anchors.margins: 22 // arbitrary spacing to key outlines | ||||
128 | } | ||||
129 | } | ||||
130 | } | ||||
131 | | ||||
132 | Component { | ||||
133 | id: rowComponent | ||||
134 | | ||||
135 | Item { | ||||
136 | property QtObject row: null | ||||
137 | x: row.left | ||||
138 | y: row.top | ||||
139 | width: childrenRect.width+4 | ||||
140 | height: childrenRect.height+4 | ||||
141 | | ||||
142 | Component.onCompleted: { | ||||
143 | for (var i in row.keys) { | ||||
144 | var key = row.keys[i] | ||||
145 | keyComponent.createObject(this, { key: key }); | ||||
146 | } | ||||
147 | } | ||||
148 | } | ||||
149 | } | ||||
150 | | ||||
151 | Component { | ||||
152 | id: sectionComponent | ||||
153 | | ||||
154 | Item { | ||||
155 | property QtObject section | ||||
156 | x: section.left | ||||
157 | y: section.top | ||||
158 | z: section.priority | ||||
159 | // Dimension defintions can be a bit wonky for sections but overally should not | ||||
160 | // cause problems even when they are (so long as we don't actually render the | ||||
161 | // sections themself) | ||||
162 | width: section.width | ||||
163 | height: section.height | ||||
164 | | ||||
165 | // Fix rotation to mod90, we cannot spin around as that'd put the text upside down ;) | ||||
166 | // Unclear if spinning around like that is in fact desired for anyting, if so I guess | ||||
167 | // we need to counter rotate text or something. | ||||
168 | rotation: section.angle != 0 ? section.angle % 90 : section.angle | ||||
169 | transformOrigin: Item.TopLeft | ||||
170 | | ||||
171 | Component.onCompleted: { | ||||
172 | for (var i in section.rows) { | ||||
173 | var row = section.rows[i] | ||||
174 | rowComponent.createObject(this, { row: row }); | ||||
175 | } | ||||
176 | | ||||
177 | for (var i in section.doodads) { | ||||
178 | var doodad = section.doodads[i] | ||||
179 | createDoodad(doodad, kbd, { doodad: doodad }) | ||||
180 | } | ||||
181 | | ||||
182 | } | ||||
183 | } | ||||
184 | } | ||||
185 | | ||||
186 | Component.onCompleted: { | ||||
187 | // Based on the geometry aspect we scale either width or height to scale so | ||||
188 | // the default size is fitting. NB: geom dimensions are mm! | ||||
189 | if (geometry.widthMM >= geometry.heightMM) { | ||||
190 | height = width * geometry.heightMM / geometry.widthMM | ||||
191 | } else { | ||||
192 | width = height * geometry.widthMM / geometry.heightMM | ||||
193 | } | ||||
194 | | ||||
195 | for (var i in geometry.sections) { | ||||
196 | var section = geometry.sections[i] | ||||
197 | sectionComponent.createObject(kbd, { section: section }); | ||||
198 | } | ||||
199 | | ||||
200 | for (var i in geometry.doodads) { | ||||
201 | var doodad = geometry.doodads[i] | ||||
202 | createDoodad(doodad, kbd, { doodad: doodad }) | ||||
203 | } | ||||
204 | | ||||
205 | visible = true | ||||
206 | } | ||||
207 | } |