Merge lp:~jonas-drange/ubuntu-system-settings/hwKeyboardMinimal into lp:ubuntu-system-settings
- hwKeyboardMinimal
- Merge into trunk
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Jonas G. Drange | ||||||||
Approved revision: | 1589 | ||||||||
Merged at revision: | 1623 | ||||||||
Proposed branch: | lp:~jonas-drange/ubuntu-system-settings/hwKeyboardMinimal | ||||||||
Merge into: | lp:ubuntu-system-settings | ||||||||
Diff against target: |
1707 lines (+1014/-345) 17 files modified
debian/control (+1/-0) plugins/language/CMakeLists.txt (+7/-4) plugins/language/KeyboardLayoutItem.qml (+65/-34) plugins/language/KeyboardLayouts.qml (+114/-5) plugins/language/PageComponent.qml (+34/-19) plugins/language/PageHardwareKeyboard.qml (+75/-0) plugins/language/hardwarekeyboard-plugin.cpp (+224/-0) plugins/language/hardwarekeyboard-plugin.h (+75/-0) plugins/language/keyboard-layout.cpp (+3/-1) plugins/language/language-plugin.cpp (+13/-261) plugins/language/language-plugin.h (+2/-20) plugins/language/onscreenkeyboard-plugin.cpp (+294/-0) plugins/language/onscreenkeyboard-plugin.h (+75/-0) plugins/language/plugin.cpp (+4/-0) plugins/language/subset-model.cpp (+24/-0) plugins/language/subset-model.h (+3/-0) tests/autopilot/ubuntu_system_settings/__init__.py (+1/-1) |
||||||||
To merge this branch: | bzr merge lp:~jonas-drange/ubuntu-system-settings/hwKeyboardMinimal | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ken VanDine | Approve | ||
Review via email: mp+281213@code.launchpad.net |
Commit message
Add External Keyboard panel which allows for configuration of the default keymap.
Description of the change
* Refactors some bits in the language plugin and keyboard layouts to make them work well with both OSK and external keyboards.
* Add a External Keyboard panel that allows for manipulation of input sources.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1578
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1579
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1580
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1582
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1583
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ken VanDine (ken-vandine) wrote : | # |
See inline comments
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1584
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Lukáš Tinkl (lukas-kde) wrote : | # |
Some inline comments
Jonas G. Drange (jonas-drange) wrote : | # |
Addressing comments from Lukáš and Ken. Thanks guys!
Lukáš Tinkl (lukas-kde) wrote : | # |
See inline comments
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1585
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Ken VanDine (ken-vandine) wrote : | # |
I'm happy with the code, during testing it didn't appear to show the hardware keyboard stuff. I'm guessing UnityInputInfo.
Ken VanDine (ken-vandine) wrote : | # |
I got it working (I had install problems before) however I noticed the first time I open the lang panel it shows 0 layouts for the hardware keyboards. Shouldn't there be some default set?
Jonas G. Drange (jonas-drange) wrote : | # |
> I got it working (I had install problems before) however I noticed the first
> time I open the lang panel it shows 0 layouts for the hardware keyboards.
> Shouldn't there be some default set?
InputSources could be empty. If we want a default, then it needs to be set in the AccountsService schema.
Ken VanDine (ken-vandine) wrote : | # |
OK, I think there should be a default, but that has to be set elsewhere.
Jonas G. Drange (jonas-drange) wrote : | # |
On 9 February 2016 at 15:26, Ken VanDine <email address hidden> wrote:
> Review: Approve
>
> OK, I think there should be a default, but that has to be set elsewhere.
>
I agree and filed bug 1543617. Thanks!
Lukáš Tinkl (lukas-kde) wrote : | # |
I'm still not getting the panel on my laptop, only on the phone
Jonas G. Drange (jonas-drange) wrote : | # |
On 11 February 2016 at 22:01, Lukáš Tinkl <email address hidden> wrote:
> I'm still not getting the panel on my laptop, only on the phone
>
It could be that the input detector is lacking. We'll then have to wait
for [1] to land. We can do that.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1588
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 1589. By Jonas G. Drange
-
sync with trunk
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2016-03-12 03:41:03 +0000 |
3 | +++ debian/control 2016-03-14 14:37:14 +0000 |
4 | @@ -31,6 +31,7 @@ |
5 | qtbase5-dev, |
6 | qtdeclarative5-dev, |
7 | libapt-pkg-dev, |
8 | + libgnome-desktop-3-dev, |
9 | # test-deps |
10 | qml-module-qttest, |
11 | qml-module-qtquick2, |
12 | |
13 | === modified file 'plugins/language/CMakeLists.txt' |
14 | --- plugins/language/CMakeLists.txt 2014-09-02 15:44:19 +0000 |
15 | +++ plugins/language/CMakeLists.txt 2016-03-14 14:37:14 +0000 |
16 | @@ -1,4 +1,5 @@ |
17 | -include_directories(${GLIB_INCLUDE_DIRS} ${ACCOUNTSSERVICE_INCLUDE_DIRS} ${ICU_INCLUDE_DIRS}) |
18 | +pkg_search_module(GD3 REQUIRED gnome-desktop-3.0) |
19 | +include_directories(${GD3_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${ACCOUNTSSERVICE_INCLUDE_DIRS} ${ICU_INCLUDE_DIRS}) |
20 | add_definitions(-DQT_NO_KEYWORDS) |
21 | |
22 | set(QML_SOURCES |
23 | @@ -6,17 +7,19 @@ |
24 | KeyboardLayoutItem.qml |
25 | KeyboardLayouts.qml |
26 | PageComponent.qml |
27 | + PageHardwareKeyboard.qml |
28 | RebootNecessary.qml |
29 | SpellChecking.qml |
30 | SubsetView.qml |
31 | ) |
32 | |
33 | + |
34 | add_library(UbuntuLanguagePlugin MODULE |
35 | - keyboard-layout.cpp language-plugin.cpp plugin.cpp subset-model.cpp |
36 | - keyboard-layout.h language-plugin.h plugin.h subset-model.h |
37 | + keyboard-layout.cpp language-plugin.cpp plugin.cpp subset-model.cpp onscreenkeyboard-plugin.cpp hardwarekeyboard-plugin.cpp |
38 | + keyboard-layout.h language-plugin.h plugin.h subset-model.h onscreenkeyboard-plugin.h hardwarekeyboard-plugin.h |
39 | ${QML_SOURCES}) |
40 | qt5_use_modules(UbuntuLanguagePlugin Qml Quick DBus) |
41 | -target_link_libraries(UbuntuLanguagePlugin uss-sessionservice ${GLIB_LDFLAGS} ${GIO_LDFLAGS} ${ACCOUNTSSERVICE_LDFLAGS} ${ICU_LDFLAGS}) |
42 | +target_link_libraries(UbuntuLanguagePlugin uss-accountsservice uss-sessionservice ${GD3_LDFLAGS} ${GLIB_LDFLAGS} ${GIO_LDFLAGS} ${ACCOUNTSSERVICE_LDFLAGS} ${ICU_LDFLAGS}) |
43 | |
44 | set(PLUG_DIR ${PLUGIN_PRIVATE_MODULE_DIR}/Ubuntu/SystemSettings/LanguagePlugin) |
45 | install(TARGETS UbuntuLanguagePlugin DESTINATION ${PLUG_DIR}) |
46 | |
47 | === modified file 'plugins/language/KeyboardLayoutItem.qml' |
48 | --- plugins/language/KeyboardLayoutItem.qml 2015-08-10 13:31:45 +0000 |
49 | +++ plugins/language/KeyboardLayoutItem.qml 2016-03-14 14:37:14 +0000 |
50 | @@ -22,49 +22,80 @@ |
51 | import Ubuntu.Components 1.3 |
52 | import Ubuntu.Components.ListItems 1.3 as ListItem |
53 | |
54 | -ListItem.Base { |
55 | +ListItem.Empty { |
56 | + id: root |
57 | property alias name: name.text |
58 | property alias checked: checkBox.checked |
59 | property alias shortName: shortName.text |
60 | - |
61 | - Row { |
62 | - anchors.top: parent.top |
63 | - anchors.left: parent.left |
64 | - anchors.bottom: parent.bottom |
65 | - spacing: units.gu(1) |
66 | - |
67 | - Rectangle { |
68 | - width: units.gu(3.0) |
69 | - height: units.gu(3.0) |
70 | - radius: units.gu(0.5) |
71 | - |
72 | - color: Theme.palette.normal.backgroundText |
73 | - |
74 | - anchors.verticalCenter: parent.verticalCenter |
75 | - |
76 | - Label { |
77 | - id: shortName |
78 | - |
79 | - color: Theme.palette.normal.background |
80 | - fontSize: "small" |
81 | - |
82 | - anchors.centerIn: parent |
83 | - } |
84 | + property alias draggable: dragHandle.visible |
85 | + property alias dragger: dragArea.drag |
86 | + |
87 | + signal dragStarted() |
88 | + signal dragFinished() |
89 | + |
90 | + Rectangle { |
91 | + id: icon |
92 | + anchors { |
93 | + left: parent.left |
94 | + leftMargin: units.gu(2) |
95 | } |
96 | + width: units.gu(3.0) |
97 | + height: units.gu(3.0) |
98 | + radius: units.gu(0.5) |
99 | + |
100 | + color: Theme.palette.normal.backgroundText |
101 | + |
102 | + anchors.verticalCenter: parent.verticalCenter |
103 | |
104 | Label { |
105 | - id: name |
106 | - |
107 | - anchors.verticalCenter: parent.verticalCenter |
108 | - } |
109 | + id: shortName |
110 | + |
111 | + color: Theme.palette.normal.background |
112 | + fontSize: "small" |
113 | + |
114 | + anchors.centerIn: parent |
115 | + } |
116 | + } |
117 | + |
118 | + Label { |
119 | + id: name |
120 | + anchors { |
121 | + left: icon.right |
122 | + leftMargin: units.gu(2) |
123 | + right: dragHandle.visible ? dragHandle.left : checkBox.left |
124 | + rightMargin: units.gu(3) |
125 | + } |
126 | + elide: Text.ElideMiddle |
127 | + anchors.verticalCenter: parent.verticalCenter |
128 | + } |
129 | + |
130 | + Icon { |
131 | + id: dragHandle |
132 | + width: units.gu(2.5) |
133 | + height: parent.height |
134 | + anchors { |
135 | + right: checkBox.left |
136 | + rightMargin: units.gu(3) |
137 | + verticalCenter: parent.verticalCenter |
138 | + } |
139 | + |
140 | + MouseArea { |
141 | + id: dragArea |
142 | + anchors.fill: parent |
143 | + |
144 | + onPressed: root.dragStarted() |
145 | + onReleased: root.dragFinished() |
146 | + } |
147 | + |
148 | + name: "grip-large" |
149 | } |
150 | |
151 | CheckBox { |
152 | id: checkBox |
153 | - |
154 | - anchors.right: parent.right |
155 | - anchors.verticalCenter: parent.verticalCenter |
156 | + anchors { |
157 | + right: parent.right |
158 | + rightMargin: units.gu(2) |
159 | + verticalCenter: parent.verticalCenter |
160 | + } |
161 | } |
162 | - |
163 | - onClicked: checked = !checked |
164 | } |
165 | |
166 | === modified file 'plugins/language/KeyboardLayouts.qml' |
167 | --- plugins/language/KeyboardLayouts.qml 2015-08-06 18:59:59 +0000 |
168 | +++ plugins/language/KeyboardLayouts.qml 2016-03-14 14:37:14 +0000 |
169 | @@ -18,16 +18,23 @@ |
170 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
171 | */ |
172 | |
173 | +import QtQuick 2.4 |
174 | import SystemSettings 1.0 |
175 | +import Ubuntu.Components 1.3 |
176 | import Ubuntu.Components.ListItems 1.3 as ListItem |
177 | import Ubuntu.SystemSettings.LanguagePlugin 1.0 |
178 | |
179 | ItemPage { |
180 | + id: root |
181 | title: i18n.tr("Keyboard layouts") |
182 | |
183 | - UbuntuLanguagePlugin { |
184 | - id: plugin |
185 | - } |
186 | + property var plugin |
187 | + property bool currentLayoutsDraggable: false |
188 | + property bool draggingCurrentLayouts: false |
189 | + property double originalContentY: 0 |
190 | + |
191 | + // Empty height + ThinDivider height |
192 | + readonly property double listItemHeight: units.gu(6) + units.dp(2) |
193 | |
194 | SubsetView { |
195 | id: subsetView |
196 | @@ -36,16 +43,36 @@ |
197 | |
198 | anchors.fill: parent |
199 | |
200 | - subsetLabel: i18n.tr("Current layouts:") |
201 | - supersetLabel: i18n.tr("All layouts available:") |
202 | + section.property: "subset" |
203 | + section.delegate: ListItem.Standard { |
204 | + text: section == "true" ? i18n.tr("Current layouts:") : i18n.tr("All layouts available:") |
205 | + |
206 | + // Fade out if it's “All layouts available” and we're draggingCurrentLayouts |
207 | + opacity: section != "true" && draggingCurrentLayouts ? 0 : 1 |
208 | + } |
209 | |
210 | model: plugin.keyboardLayoutsModel |
211 | delegate: KeyboardLayoutItem { |
212 | + id: item |
213 | + anchors { |
214 | + left: parent.left |
215 | + right: parent.right |
216 | + } |
217 | + |
218 | + Behavior on height { enabled: visible; UbuntuNumberAnimation { } } |
219 | + |
220 | name: model.language |
221 | shortName: model.icon |
222 | checked: model.checked |
223 | enabled: model.enabled |
224 | |
225 | + draggable: (currentLayoutsDraggable && |
226 | + model.subset && |
227 | + subsetView.model.subset.length > 1) |
228 | + |
229 | + visible: root.draggingCurrentLayouts ? model.subset : true |
230 | + opacity: root.draggingCurrentLayouts ? 0.75 : 1 |
231 | + |
232 | onCheckedChanged: { |
233 | var element = model.index < subsetView.model.subset.length ? |
234 | subsetView.model.subset[model.index] : |
235 | @@ -55,6 +82,88 @@ |
236 | |
237 | checked = Qt.binding(function() { return model.checked }) |
238 | } |
239 | + |
240 | + onDragStarted: { |
241 | + |
242 | + // If the element is not checked, refuse dragging. |
243 | + if (!model.checked) { |
244 | + return; |
245 | + } |
246 | + root.draggingCurrentLayouts = true; |
247 | + |
248 | + // Force scroll to top |
249 | + subsetView.contentY = -listItemHeight |
250 | + |
251 | + dragger.target = dragItem; |
252 | + dragger.maximumX = units.gu(1); |
253 | + dragger.minimumX = units.gu(1); |
254 | + |
255 | + dragger.minimumY = listItemHeight + (listItemHeight / 2) |
256 | + dragger.maximumY = listItemHeight * (0.5 + subsetView.model.subset.length) |
257 | + |
258 | + dragItem.name = name; |
259 | + dragItem.shortName = shortName; |
260 | + dragItem.checked = checked; |
261 | + dragItem.enabled = enabled; |
262 | + dragItem.originalY = mapToItem(root, 0, 0).y; |
263 | + dragItem.originalIndex = index; |
264 | + dragItem.y = dragItem.originalY; |
265 | + dragItem.x = units.gu(1); |
266 | + dragItem.visible = true; |
267 | + dragItem.elementToShrink = item; |
268 | + } |
269 | + |
270 | + onDragFinished: { |
271 | + root.draggingCurrentLayouts = false; |
272 | + dragger.target = undefined; |
273 | + dragItem.visible = false; |
274 | + if (dragMarker.visible && dragMarker.index != index) { |
275 | + plugin.requestCurrentLayoutMove(dragItem.originalIndex, dragMarker.index); |
276 | + } |
277 | + dragMarker.visible = false; |
278 | + dragItem.elementToShrink.height = listItemHeight; |
279 | + dragItem.elementToShrink.clip = false; |
280 | + dragItem.elementToShrink = null; |
281 | + } |
282 | + } |
283 | + } |
284 | + |
285 | + ListItem.ThinDivider { |
286 | + id: dragMarker |
287 | + visible: false |
288 | + property int index: { |
289 | + var midOfDragItem = dragItem.y - (dragItem.height / 2) - listItemHeight; |
290 | + var origi = Math.round(midOfDragItem / listItemHeight) |
291 | + var i = Math.round(midOfDragItem / listItemHeight) |
292 | + if (i < 0) i = 0; |
293 | + if (i >= subsetView.model.subset.length - 1) { |
294 | + i = subsetView.model.subset.length - 1; |
295 | + } |
296 | + return i; |
297 | + } |
298 | + y: ((index + 2) * listItemHeight) - height / 2 |
299 | + height: units.gu(1) |
300 | + } |
301 | + |
302 | + KeyboardLayoutItem { |
303 | + id: dragItem |
304 | + |
305 | + property real originalY |
306 | + property int originalIndex |
307 | + property var elementToShrink: null |
308 | + |
309 | + objectName: "dragItem" |
310 | + visible: false |
311 | + opacity: 0.9 |
312 | + style: Rectangle { |
313 | + color: Theme.palette.selected.background |
314 | + } |
315 | + onYChanged: { |
316 | + if (!dragMarker.visible && Math.abs(y - originalY) >= height / 2) { |
317 | + dragMarker.visible = true; |
318 | + dragItem.elementToShrink.clip = true; |
319 | + elementToShrink.height = 0.01; |
320 | + } |
321 | } |
322 | } |
323 | } |
324 | |
325 | === modified file 'plugins/language/PageComponent.qml' |
326 | --- plugins/language/PageComponent.qml 2015-08-10 13:31:45 +0000 |
327 | +++ plugins/language/PageComponent.qml 2016-03-14 14:37:14 +0000 |
328 | @@ -19,6 +19,7 @@ |
329 | */ |
330 | |
331 | import QtQuick 2.4 |
332 | +import QtSystemInfo 5.5 |
333 | import GSettings 1.0 |
334 | import SystemSettings 1.0 |
335 | import Ubuntu.Components 1.3 |
336 | @@ -33,10 +34,21 @@ |
337 | |
338 | title: i18n.tr("Language & Text") |
339 | |
340 | + InputDeviceManager { |
341 | + id: keyboardsModel |
342 | + filter: InputInfo.Keyboard |
343 | + } |
344 | + |
345 | + property bool externalKeyboardPresent: keyboardsModel.count > 0 |
346 | + |
347 | UbuntuLanguagePlugin { |
348 | id: plugin |
349 | } |
350 | |
351 | + OnScreenKeyboardPlugin { |
352 | + id: oskPlugin |
353 | + } |
354 | + |
355 | Component { |
356 | id: displayLanguage |
357 | |
358 | @@ -50,12 +62,6 @@ |
359 | } |
360 | |
361 | Component { |
362 | - id: keyboardLayouts |
363 | - |
364 | - KeyboardLayouts {} |
365 | - } |
366 | - |
367 | - Component { |
368 | id: spellChecking |
369 | |
370 | SpellChecking {} |
371 | @@ -100,6 +106,7 @@ |
372 | iconSource: "image://theme/language-chooser" |
373 | text: i18n.tr("Display language…") |
374 | objectName: "displayLanguage" |
375 | + showDivider: false |
376 | component: Label { |
377 | property int currentLanguage: plugin.currentLanguage |
378 | objectName: "currentLanguage" |
379 | @@ -111,21 +118,29 @@ |
380 | onClicked: PopupUtils.open(displayLanguage) |
381 | } |
382 | |
383 | - ListItem.Divider { |
384 | - } |
385 | + ListItem.Divider {} |
386 | |
387 | ListItem.SingleValue { |
388 | - text: i18n.tr("Keyboard layouts") |
389 | - value: plugin.keyboardLayoutsModel.subset.length == 1 ? |
390 | - plugin.keyboardLayoutsModel.superset[plugin.keyboardLayoutsModel.subset[0]][0] : |
391 | - plugin.keyboardLayoutsModel.subset.length |
392 | - progression: true |
393 | - |
394 | - onClicked: pageStack.push(keyboardLayouts) |
395 | - } |
396 | - |
397 | - ListItem.Divider { |
398 | - } |
399 | + text: externalKeyboardPresent ? i18n.tr("On-screen keyboard") : |
400 | + i18n.tr("Keyboard layouts") |
401 | + progression: true |
402 | + value: oskPlugin.keyboardLayoutsModel.subset.length == 1 ? |
403 | + oskPlugin.keyboardLayoutsModel.superset[oskPlugin.keyboardLayoutsModel.subset[0]][0] : |
404 | + oskPlugin.keyboardLayoutsModel.subset.length |
405 | + onClicked: pageStack.push(Qt.resolvedUrl("KeyboardLayouts.qml"), { |
406 | + plugin: oskPlugin |
407 | + }) |
408 | + } |
409 | + |
410 | + ListItem.Standard { |
411 | + text: i18n.tr("External keyboard") |
412 | + progression: true |
413 | + showDivider: false |
414 | + onClicked: pageStack.push(Qt.resolvedUrl("PageHardwareKeyboard.qml")) |
415 | + visible: externalKeyboardPresent |
416 | + } |
417 | + |
418 | + ListItem.Divider {} |
419 | |
420 | ListItem.SingleValue { |
421 | visible: showAllUI |
422 | |
423 | === added file 'plugins/language/PageHardwareKeyboard.qml' |
424 | --- plugins/language/PageHardwareKeyboard.qml 1970-01-01 00:00:00 +0000 |
425 | +++ plugins/language/PageHardwareKeyboard.qml 2016-03-14 14:37:14 +0000 |
426 | @@ -0,0 +1,75 @@ |
427 | +/* |
428 | + * This file is part of system-settings |
429 | + * |
430 | + * Copyright (C) 2015 Canonical Ltd. |
431 | + * |
432 | + * Contact: William Hua <william.hua@canonical.com> |
433 | + * Jonas G. Drange <jonas.drange@canonical.com> |
434 | + * |
435 | + * This program is free software: you can redistribute it and/or modify it |
436 | + * under the terms of the GNU General Public License version 3, as published |
437 | + * by the Free Software Foundation. |
438 | + * |
439 | + * This program is distributed in the hope that it will be useful, but |
440 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
441 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
442 | + * PURPOSE. See the GNU General Public License for more details. |
443 | + * |
444 | + * You should have received a copy of the GNU General Public License along |
445 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
446 | + */ |
447 | + |
448 | +import QtQuick 2.0 |
449 | +import SystemSettings 1.0 |
450 | +import Ubuntu.Components 1.3 |
451 | +import Ubuntu.Components.ListItems 1.3 as ListItem |
452 | +import Ubuntu.Settings.Components 0.1 as USC |
453 | +import Ubuntu.Settings.Menus 0.1 as Menus |
454 | +import Ubuntu.SystemSettings.LanguagePlugin 1.0 |
455 | + |
456 | +ItemPage { |
457 | + id: root |
458 | + objectName: "hwKbdPage" |
459 | + |
460 | + title: i18n.tr("Hardware keyboard") |
461 | + |
462 | + Component { |
463 | + id: keyboardLayouts |
464 | + |
465 | + KeyboardLayouts {} |
466 | + } |
467 | + |
468 | + HardwareKeyboardPlugin { |
469 | + id: plugin |
470 | + } |
471 | + |
472 | + Flickable { |
473 | + anchors.fill: parent |
474 | + contentHeight: contentItem.childrenRect.height |
475 | + boundsBehavior: contentHeight > root.height ? |
476 | + Flickable.DragAndOvershootBounds : |
477 | + Flickable.StopAtBounds |
478 | + /* Set the direction to workaround https://bugreports.qt-project.org/browse/QTBUG-31905 |
479 | + otherwise the UI might end up in a situation where scrolling doesn't work */ |
480 | + flickableDirection: Flickable.VerticalFlick |
481 | + |
482 | + Column { |
483 | + anchors.left: parent.left |
484 | + anchors.right: parent.right |
485 | + |
486 | + |
487 | + ListItem.SingleValue { |
488 | + text: i18n.tr("Layouts and other sources") |
489 | + value: plugin.keyboardLayoutsModel.subset.length == 1 ? |
490 | + plugin.keyboardLayoutsModel.superset[plugin.keyboardLayoutsModel.subset[0]][0] : |
491 | + plugin.keyboardLayoutsModel.subset.length |
492 | + progression: true |
493 | + |
494 | + onClicked: pageStack.push(Qt.resolvedUrl("KeyboardLayouts.qml"), { |
495 | + plugin: plugin, |
496 | + currentLayoutsDraggable: true |
497 | + }) |
498 | + } |
499 | + } |
500 | + } |
501 | +} |
502 | |
503 | === added file 'plugins/language/hardwarekeyboard-plugin.cpp' |
504 | --- plugins/language/hardwarekeyboard-plugin.cpp 1970-01-01 00:00:00 +0000 |
505 | +++ plugins/language/hardwarekeyboard-plugin.cpp 2016-03-14 14:37:14 +0000 |
506 | @@ -0,0 +1,224 @@ |
507 | +/* |
508 | + * This file is part of system-settings |
509 | + * |
510 | + * Copyright (C) 2015 Canonical Ltd. |
511 | + * |
512 | + * Contact: William Hua <william.hua@canonical.com> |
513 | + * Jonas G. Drange <jonas.drange@canonical.com> |
514 | + * |
515 | + * This program is free software: you can redistribute it and/or modify it |
516 | + * under the terms of the GNU General Public License version 3, as published |
517 | + * by the Free Software Foundation. |
518 | + * |
519 | + * This program is distributed in the hope that it will be useful, but |
520 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
521 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
522 | + * PURPOSE. See the GNU General Public License for more details. |
523 | + * |
524 | + * You should have received a copy of the GNU General Public License along |
525 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
526 | + */ |
527 | + |
528 | +#include <QDBusMetaType> |
529 | +#include <QtAlgorithms> |
530 | +#include <QtDebug> |
531 | +#include "hardwarekeyboard-plugin.h" |
532 | + |
533 | +#define INPUT_SOURCE_TYPE_XKB "xkb" |
534 | + |
535 | +typedef QList<QMap<QString, QString>> StringMapList; |
536 | +Q_DECLARE_METATYPE(StringMapList) |
537 | + |
538 | +HardwareKeyboardPlugin::HardwareKeyboardPlugin(QObject *parent) : |
539 | + QObject(parent) |
540 | +{ |
541 | + qDBusRegisterMetaType<StringMapList>(); |
542 | + m_xkbInfo = gnome_xkb_info_new(); |
543 | + |
544 | + updateKeyboardLayouts(); |
545 | + updateKeyboardLayoutsModel(); |
546 | +} |
547 | + |
548 | + |
549 | +HardwareKeyboardPlugin::~HardwareKeyboardPlugin() |
550 | +{ |
551 | + if (m_xkbInfo != nullptr) { |
552 | + g_object_unref(m_xkbInfo); |
553 | + } |
554 | + |
555 | + qDeleteAll(m_keyboardLayouts); |
556 | +} |
557 | + |
558 | +SubsetModel * |
559 | +HardwareKeyboardPlugin::keyboardLayoutsModel() |
560 | +{ |
561 | + return &m_keyboardLayoutsModel; |
562 | +} |
563 | + |
564 | +void |
565 | +HardwareKeyboardPlugin::keyboardLayoutsModelChanged() |
566 | +{ |
567 | + QVariant answer = m_accountsService.getUserProperty( |
568 | + "org.freedesktop.Accounts.User", |
569 | + "InputSources"); |
570 | + StringMapList maps; |
571 | + if (answer.isValid()) { |
572 | + QDBusArgument arg = answer.value<QDBusArgument>(); |
573 | + maps = qdbus_cast<StringMapList>(arg); |
574 | + } else { |
575 | + qCritical() << "failed to get input sources"; |
576 | + return; |
577 | + } |
578 | + |
579 | + StringMapList finalMaps = StringMapList(); |
580 | + for (int i = 0; i < maps.size(); i++) { |
581 | + QMap<QString, QString> m = maps.at(i); |
582 | + |
583 | + // Keep any maps not of xkb type (ibus e.g.) |
584 | + if (!m.contains(INPUT_SOURCE_TYPE_XKB)) { |
585 | + finalMaps.append(m); |
586 | + } |
587 | + } |
588 | + |
589 | + // Update maps with what the user selected. |
590 | + QList<int> subset = m_keyboardLayoutsModel.subset(); |
591 | + |
592 | + // The first top item selected by the user will appear as the first map. |
593 | + QListIterator<int> it(subset); |
594 | + it.toBack(); |
595 | + while (it.hasPrevious()) { |
596 | + QMap<QString, QString> m = QMap<QString, QString>(); |
597 | + KeyboardLayout* layout = m_keyboardLayouts.at(it.previous()); |
598 | + m.insert(INPUT_SOURCE_TYPE_XKB, layout->name()); |
599 | + finalMaps.prepend(m); |
600 | + } |
601 | + |
602 | + m_accountsService.customSetUserProperty( |
603 | + "SetInputSources", QVariant::fromValue(finalMaps)); |
604 | +} |
605 | + |
606 | +static bool |
607 | +compareLayouts(const KeyboardLayout *layout0, |
608 | + const KeyboardLayout *layout1) |
609 | +{ |
610 | + QString name0(layout0->displayName()); |
611 | + QString name1(layout1->displayName()); |
612 | + |
613 | + if (name0 == name1) { |
614 | + name0 = layout0->language(); |
615 | + name1 = layout1->language(); |
616 | + |
617 | + if (name0 == name1) { |
618 | + name0 = layout0->name(); |
619 | + name1 = layout1->name(); |
620 | + } |
621 | + } |
622 | + |
623 | + return QString::localeAwareCompare(name0, name1) < 0; |
624 | +} |
625 | + |
626 | +void |
627 | +HardwareKeyboardPlugin::updateKeyboardLayouts() |
628 | +{ |
629 | + GList *sources, *tmp; |
630 | + gchar *source_id = NULL; |
631 | + const gchar *display_name; |
632 | + const gchar *short_name; |
633 | + const gchar *xkb_layout; |
634 | + const gchar *xkb_variant; |
635 | + sources = gnome_xkb_info_get_all_layouts(m_xkbInfo); |
636 | + |
637 | + m_keyboardLayouts.clear(); |
638 | + |
639 | + for (tmp = sources; tmp != NULL; tmp = tmp->next) { |
640 | + g_free (source_id); |
641 | + source_id = g_strconcat(INPUT_SOURCE_TYPE_XKB, tmp->data, NULL); |
642 | + |
643 | + gnome_xkb_info_get_layout_info(m_xkbInfo, (const gchar *)tmp->data, |
644 | + &display_name, &short_name, &xkb_layout, &xkb_variant); |
645 | + |
646 | + KeyboardLayout *layout(new KeyboardLayout((const gchar *)tmp->data, |
647 | + short_name, |
648 | + display_name, |
649 | + xkb_variant)); |
650 | + if (!layout->language().isEmpty()) |
651 | + m_keyboardLayouts += layout; |
652 | + else |
653 | + delete layout; |
654 | + |
655 | + } |
656 | + g_free(source_id); |
657 | + g_list_free(sources); |
658 | + qSort(m_keyboardLayouts.begin(), m_keyboardLayouts.end(), compareLayouts); |
659 | +} |
660 | + |
661 | +void |
662 | +HardwareKeyboardPlugin::updateKeyboardLayoutsModel() |
663 | +{ |
664 | + QStringList customRoles; |
665 | + customRoles += "language"; |
666 | + customRoles += "icon"; |
667 | + |
668 | + m_keyboardLayoutsModel.setCustomRoles(customRoles); |
669 | + |
670 | + QVariantList superset; |
671 | + |
672 | + for (QList<KeyboardLayout *>::const_iterator |
673 | + i(m_keyboardLayouts.begin()); i != m_keyboardLayouts.end(); ++i) { |
674 | + QVariantList element; |
675 | + |
676 | + if (!(*i)->displayName().isEmpty()) |
677 | + element += (*i)->displayName(); |
678 | + else |
679 | + element += (*i)->name(); |
680 | + |
681 | + element += (*i)->shortName(); |
682 | + superset += QVariant(element); |
683 | + } |
684 | + |
685 | + m_keyboardLayoutsModel.setSuperset(superset); |
686 | + |
687 | + enabledLayoutsChanged(); |
688 | + |
689 | + connect(&m_keyboardLayoutsModel, |
690 | + SIGNAL(subsetChanged()), |
691 | + SLOT(keyboardLayoutsModelChanged())); |
692 | +} |
693 | + |
694 | +void |
695 | +HardwareKeyboardPlugin::enabledLayoutsChanged() |
696 | +{ |
697 | + QList<int> subset; |
698 | + |
699 | + QVariant answer = m_accountsService.getUserProperty( |
700 | + "org.freedesktop.Accounts.User", |
701 | + "InputSources"); |
702 | + |
703 | + if (answer.isValid()) { |
704 | + QDBusArgument arg = answer.value<QDBusArgument>(); |
705 | + StringMapList list = qdbus_cast<StringMapList>(arg); |
706 | + |
707 | + for (int i = 0; i < list.length(); ++i) { |
708 | + for (int j = 0; j < m_keyboardLayouts.length(); j++) { |
709 | + if (m_keyboardLayouts[j]->name() == list.at(i)[INPUT_SOURCE_TYPE_XKB]) { |
710 | + subset += j; |
711 | + break; |
712 | + } |
713 | + } |
714 | + } |
715 | + m_keyboardLayoutsModel.setSubset(subset); |
716 | + } else { |
717 | + qCritical() << "failed to get input sources"; |
718 | + } |
719 | +} |
720 | + |
721 | +void HardwareKeyboardPlugin::setCurrentLayout(const QString &code) |
722 | +{ |
723 | + Q_UNUSED(code); |
724 | + // TODO: Implement. |
725 | +} |
726 | + |
727 | +void HardwareKeyboardPlugin::requestCurrentLayoutMove(const int from, const int to) { |
728 | + m_keyboardLayoutsModel.moveSubsetRow(from, to); |
729 | + keyboardLayoutsModelChanged(); |
730 | +} |
731 | |
732 | === added file 'plugins/language/hardwarekeyboard-plugin.h' |
733 | --- plugins/language/hardwarekeyboard-plugin.h 1970-01-01 00:00:00 +0000 |
734 | +++ plugins/language/hardwarekeyboard-plugin.h 2016-03-14 14:37:14 +0000 |
735 | @@ -0,0 +1,75 @@ |
736 | +/* |
737 | + * This file is part of system-settings |
738 | + * |
739 | + * Copyright (C) 2015 Canonical Ltd. |
740 | + * |
741 | + * Contact: William Hua <william.hua@canonical.com> |
742 | + * Jonas G. Drange <jonas.drange@canonical.com> |
743 | + * |
744 | + * This program is free software: you can redistribute it and/or modify it |
745 | + * under the terms of the GNU General Public License version 3, as published |
746 | + * by the Free Software Foundation. |
747 | + * |
748 | + * This program is distributed in the hope that it will be useful, but |
749 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
750 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
751 | + * PURPOSE. See the GNU General Public License for more details. |
752 | + * |
753 | + * You should have received a copy of the GNU General Public License along |
754 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
755 | + */ |
756 | + |
757 | +#ifndef HWKBD_PLUGIN_H |
758 | +#define HWKBD_PLUGIN_H |
759 | + |
760 | +#include <QtCore> |
761 | +#include <gio/gio.h> |
762 | +#include <QDBusArgument> |
763 | + |
764 | +#define GNOME_DESKTOP_USE_UNSTABLE_API |
765 | +#include <libgnome-desktop/gnome-xkb-info.h> |
766 | + |
767 | +#include "accountsservice.h" |
768 | +#include "subset-model.h" |
769 | +#include "keyboard-layout.h" |
770 | + |
771 | +typedef void *gpointer; |
772 | +typedef char gchar; |
773 | + |
774 | +class KeyboardLayout; |
775 | + |
776 | +class HardwareKeyboardPlugin : public QObject |
777 | +{ |
778 | +private: |
779 | + |
780 | + Q_OBJECT |
781 | + |
782 | +public: |
783 | + |
784 | + Q_PROPERTY(SubsetModel *keyboardLayoutsModel |
785 | + READ keyboardLayoutsModel |
786 | + CONSTANT) |
787 | + |
788 | + explicit HardwareKeyboardPlugin(QObject *parent = nullptr); |
789 | + |
790 | + virtual ~HardwareKeyboardPlugin(); |
791 | + |
792 | + Q_INVOKABLE void setCurrentLayout(const QString &code); |
793 | + Q_INVOKABLE void requestCurrentLayoutMove(const int from, const int to); |
794 | + |
795 | + SubsetModel *keyboardLayoutsModel(); |
796 | + Q_SLOT void keyboardLayoutsModelChanged(); |
797 | + Q_SLOT void enabledLayoutsChanged(); |
798 | + |
799 | +private: |
800 | + void updateEnabledLayouts(); |
801 | + void updateKeyboardLayouts(); |
802 | + void updateKeyboardLayoutsModel(); |
803 | + |
804 | + GnomeXkbInfo *m_xkbInfo; |
805 | + QList<KeyboardLayout *> m_keyboardLayouts; |
806 | + SubsetModel m_keyboardLayoutsModel; |
807 | + AccountsService m_accountsService; |
808 | +}; |
809 | + |
810 | +#endif // HWKBD_PLUGIN_H |
811 | |
812 | === modified file 'plugins/language/keyboard-layout.cpp' |
813 | --- plugins/language/keyboard-layout.cpp 2014-07-23 13:44:31 +0000 |
814 | +++ plugins/language/keyboard-layout.cpp 2016-03-14 14:37:14 +0000 |
815 | @@ -30,8 +30,10 @@ |
816 | m_name(name), |
817 | m_language(language), |
818 | m_displayName(displayName), |
819 | - m_shortName(shortName) |
820 | + m_shortName(language) |
821 | { |
822 | + Q_UNUSED(shortName); |
823 | + m_shortName[0] = m_shortName[0].toUpper(); |
824 | } |
825 | |
826 | KeyboardLayout::KeyboardLayout(const QFileInfo &fileInfo, |
827 | |
828 | === modified file 'plugins/language/language-plugin.cpp' |
829 | --- plugins/language/language-plugin.cpp 2015-05-22 19:16:25 +0000 |
830 | +++ plugins/language/language-plugin.cpp 2016-03-14 14:37:14 +0000 |
831 | @@ -17,21 +17,14 @@ |
832 | * You should have received a copy of the GNU General Public License along |
833 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
834 | */ |
835 | - |
836 | +#include <QtDebug> |
837 | #include "language-plugin.h" |
838 | #include "keyboard-layout.h" |
839 | |
840 | #include <act/act.h> |
841 | #include <unicode/locid.h> |
842 | |
843 | -#define UBUNTU_KEYBOARD_SCHEMA_ID "com.canonical.keyboard.maliit" |
844 | - |
845 | -#define KEY_ENABLED_LAYOUTS "enabled-languages" |
846 | -#define KEY_CURRENT_LAYOUT "active-language" |
847 | -#define KEY_PLUGIN_PATHS "plugin-paths" |
848 | - |
849 | #define LANGUAGE2LOCALE "/usr/share/language-tools/language2locale" |
850 | -#define LAYOUTS_DIR "/usr/share/maliit/plugins/com/ubuntu/lib" |
851 | |
852 | static const char * const LOCALE_BLACKLIST[] = { |
853 | "C", |
854 | @@ -94,12 +87,8 @@ |
855 | m_currentLanguage(-1), |
856 | m_nextCurrentLanguage(-1), |
857 | m_manager(act_user_manager_get_default()), |
858 | - m_user(nullptr), |
859 | - m_maliitSettings(g_settings_new(UBUNTU_KEYBOARD_SCHEMA_ID)) |
860 | + m_user(nullptr) |
861 | { |
862 | - GVariantIter *iter; |
863 | - const gchar *path; |
864 | - |
865 | if (m_manager != nullptr) { |
866 | g_object_ref(m_manager); |
867 | |
868 | @@ -113,16 +102,8 @@ |
869 | G_CALLBACK(::managerLoaded), this); |
870 | } |
871 | |
872 | - m_layoutPaths.append(LAYOUTS_DIR); |
873 | - g_settings_get(m_maliitSettings, KEY_PLUGIN_PATHS, "as", &iter); |
874 | - for (int i(0); g_variant_iter_next(iter, "&s", &path); i++) { |
875 | - m_layoutPaths.append(path); |
876 | - } |
877 | updateLanguageNamesAndCodes(); |
878 | updateCurrentLanguage(); |
879 | - updateEnabledLayouts(); |
880 | - updateKeyboardLayouts(); |
881 | - updateKeyboardLayoutsModel(); |
882 | updateSpellCheckingModel(); |
883 | } |
884 | |
885 | @@ -137,15 +118,6 @@ |
886 | g_signal_handlers_disconnect_by_data(m_manager, this); |
887 | g_object_unref(m_manager); |
888 | } |
889 | - |
890 | - if (m_maliitSettings != nullptr) { |
891 | - g_signal_handlers_disconnect_by_data(m_maliitSettings, this); |
892 | - g_object_unref(m_maliitSettings); |
893 | - } |
894 | - |
895 | - for (QList<KeyboardLayout *>::const_iterator |
896 | - i(m_keyboardLayouts.begin()); i != m_keyboardLayouts.end(); ++i) |
897 | - delete *i; |
898 | } |
899 | |
900 | const QStringList & |
901 | @@ -160,6 +132,17 @@ |
902 | return m_languageCodes; |
903 | } |
904 | |
905 | +QString |
906 | +LanguagePlugin::languageToLayout(const QString &lang) |
907 | +{ |
908 | + QString language(lang.left(lang.indexOf('.'))); |
909 | + act_user_set_language(m_user, qPrintable(language)); |
910 | + act_user_set_formats_locale(m_user, qPrintable(lang)); |
911 | + |
912 | + icu::Locale locale(qPrintable(lang)); |
913 | + return locale.getLanguage(); |
914 | +} |
915 | + |
916 | int |
917 | LanguagePlugin::currentLanguage() const |
918 | { |
919 | @@ -177,72 +160,6 @@ |
920 | } |
921 | |
922 | SubsetModel * |
923 | -LanguagePlugin::keyboardLayoutsModel() |
924 | -{ |
925 | - return &m_keyboardLayoutsModel; |
926 | -} |
927 | - |
928 | -void |
929 | -LanguagePlugin::keyboardLayoutsModelChanged() |
930 | -{ |
931 | - GVariantBuilder builder; |
932 | - gchar *current; |
933 | - bool removed(true); |
934 | - |
935 | - g_variant_builder_init(&builder, G_VARIANT_TYPE("as")); |
936 | - g_settings_get(m_maliitSettings, KEY_CURRENT_LAYOUT, "s", ¤t); |
937 | - |
938 | - for (QList<int>::const_iterator |
939 | - i(m_keyboardLayoutsModel.subset().begin()); |
940 | - i != m_keyboardLayoutsModel.subset().end(); ++i) { |
941 | - g_variant_builder_add(&builder, "s", |
942 | - qPrintable(m_keyboardLayouts[*i]->name())); |
943 | - |
944 | - if (m_keyboardLayouts[*i]->name() == current) |
945 | - removed = false; |
946 | - } |
947 | - |
948 | - if (removed && !m_keyboardLayoutsModel.subset().isEmpty()) { |
949 | - GVariantIter *iter; |
950 | - const gchar *layout; |
951 | - bool found(false); |
952 | - |
953 | - g_settings_get(m_maliitSettings, KEY_ENABLED_LAYOUTS, "as", &iter); |
954 | - |
955 | - for (int i(0); g_variant_iter_next(iter, "&s", &layout); i++) { |
956 | - found = g_strcmp0(layout, current) == 0; |
957 | - |
958 | - if (found) { |
959 | - if (i >= m_keyboardLayoutsModel.subset().size()) |
960 | - i = m_keyboardLayoutsModel.subset().size() - 1; |
961 | - |
962 | - int index(m_keyboardLayoutsModel.subset()[i]); |
963 | - const QString &name(m_keyboardLayouts[index]->name()); |
964 | - |
965 | - g_settings_set_string(m_maliitSettings, |
966 | - KEY_CURRENT_LAYOUT, qPrintable(name)); |
967 | - |
968 | - break; |
969 | - } |
970 | - } |
971 | - |
972 | - if (!found) { |
973 | - int index(m_keyboardLayoutsModel.subset().front()); |
974 | - const QString &name(m_keyboardLayouts[index]->name()); |
975 | - |
976 | - g_settings_set_string(m_maliitSettings, |
977 | - KEY_CURRENT_LAYOUT, qPrintable(name)); |
978 | - } |
979 | - |
980 | - g_variant_iter_free(iter); |
981 | - } |
982 | - |
983 | - g_free(current); |
984 | - g_settings_set_value(m_maliitSettings, |
985 | - KEY_ENABLED_LAYOUTS, g_variant_builder_end(&builder)); |
986 | -} |
987 | - |
988 | -SubsetModel * |
989 | LanguagePlugin::spellCheckingModel() |
990 | { |
991 | return &m_spellCheckingModel; |
992 | @@ -254,26 +171,6 @@ |
993 | // TODO: update spell checking model |
994 | } |
995 | |
996 | -static bool |
997 | -compareLayouts(const KeyboardLayout *layout0, |
998 | - const KeyboardLayout *layout1) |
999 | -{ |
1000 | - QString name0(layout0->displayName()); |
1001 | - QString name1(layout1->displayName()); |
1002 | - |
1003 | - if (name0 == name1) { |
1004 | - name0 = layout0->language(); |
1005 | - name1 = layout1->language(); |
1006 | - |
1007 | - if (name0 == name1) { |
1008 | - name0 = layout0->name(); |
1009 | - name1 = layout1->name(); |
1010 | - } |
1011 | - } |
1012 | - |
1013 | - return QString::localeAwareCompare(name0, name1) < 0; |
1014 | -} |
1015 | - |
1016 | void |
1017 | LanguagePlugin::updateLanguageNamesAndCodes() |
1018 | { |
1019 | @@ -359,19 +256,6 @@ |
1020 | QString language(formatsLocale.left(formatsLocale.indexOf('.'))); |
1021 | act_user_set_language(m_user, qPrintable(language)); |
1022 | act_user_set_formats_locale(m_user, qPrintable(formatsLocale)); |
1023 | - |
1024 | - icu::Locale locale(qPrintable(formatsLocale)); |
1025 | - const char *code(locale.getLanguage()); |
1026 | - for (int i = 0; i < m_layoutPaths.count(); i++) { |
1027 | - QFileInfo fileInfo(QDir(m_layoutPaths.at(i)), code); |
1028 | - |
1029 | - if (fileInfo.exists() && fileInfo.isDir()) { |
1030 | - g_settings_set_string(m_maliitSettings, |
1031 | - KEY_CURRENT_LAYOUT, code); |
1032 | - |
1033 | - updateEnabledLayouts(); |
1034 | - } |
1035 | - } |
1036 | } else { |
1037 | QString formatsLocale(act_user_get_formats_locale(m_user)); |
1038 | m_currentLanguage = indexForLocale(formatsLocale); |
1039 | @@ -390,103 +274,6 @@ |
1040 | Q_EMIT currentLanguageChanged(); |
1041 | } |
1042 | |
1043 | -void |
1044 | -LanguagePlugin::updateEnabledLayouts() |
1045 | -{ |
1046 | - GVariantBuilder builder; |
1047 | - GVariantIter *iter; |
1048 | - gchar *current; |
1049 | - const gchar *layout; |
1050 | - QSet<QString> added; |
1051 | - |
1052 | - g_variant_builder_init(&builder, G_VARIANT_TYPE("as")); |
1053 | - g_settings_get(m_maliitSettings, KEY_ENABLED_LAYOUTS, "as", &iter); |
1054 | - g_settings_get(m_maliitSettings, KEY_CURRENT_LAYOUT, "s", ¤t); |
1055 | - |
1056 | - while (g_variant_iter_next(iter, "&s", &layout)) { |
1057 | - if (!added.contains(layout)) { |
1058 | - g_variant_builder_add(&builder, "s", layout); |
1059 | - added.insert(layout); |
1060 | - } |
1061 | - } |
1062 | - |
1063 | - if (!added.contains(current)) { |
1064 | - g_variant_builder_add(&builder, "s", current); |
1065 | - added.insert(current); |
1066 | - } |
1067 | - |
1068 | - g_free(current); |
1069 | - g_variant_iter_free(iter); |
1070 | - g_settings_set_value(m_maliitSettings, |
1071 | - KEY_ENABLED_LAYOUTS, g_variant_builder_end(&builder)); |
1072 | -} |
1073 | - |
1074 | -void |
1075 | -LanguagePlugin::updateKeyboardLayouts() |
1076 | -{ |
1077 | - m_keyboardLayouts.clear(); |
1078 | - |
1079 | - for (int i = 0; i < m_layoutPaths.count(); i++) { |
1080 | - QDir layoutsDir(m_layoutPaths.at(i)); |
1081 | - layoutsDir.setFilter(QDir::Dirs); |
1082 | - layoutsDir.setSorting(QDir::Name); |
1083 | - |
1084 | - QFileInfoList fileInfoList(layoutsDir.entryInfoList()); |
1085 | - |
1086 | - for (QFileInfoList::const_iterator |
1087 | - i(fileInfoList.begin()); i != fileInfoList.end(); ++i) { |
1088 | - KeyboardLayout *layout(new KeyboardLayout(*i)); |
1089 | - |
1090 | - if (!layout->language().isEmpty()) |
1091 | - m_keyboardLayouts += layout; |
1092 | - else |
1093 | - delete layout; |
1094 | - } |
1095 | - } |
1096 | - |
1097 | - qSort(m_keyboardLayouts.begin(), m_keyboardLayouts.end(), compareLayouts); |
1098 | -} |
1099 | - |
1100 | -void enabledLayoutsChanged(GSettings *settings, |
1101 | - gchar *key, |
1102 | - gpointer user_data); |
1103 | - |
1104 | -void |
1105 | -LanguagePlugin::updateKeyboardLayoutsModel() |
1106 | -{ |
1107 | - QStringList customRoles; |
1108 | - customRoles += "language"; |
1109 | - customRoles += "icon"; |
1110 | - |
1111 | - m_keyboardLayoutsModel.setCustomRoles(customRoles); |
1112 | - |
1113 | - QVariantList superset; |
1114 | - |
1115 | - for (QList<KeyboardLayout *>::const_iterator |
1116 | - i(m_keyboardLayouts.begin()); i != m_keyboardLayouts.end(); ++i) { |
1117 | - QVariantList element; |
1118 | - |
1119 | - if (!(*i)->displayName().isEmpty()) |
1120 | - element += (*i)->displayName(); |
1121 | - else |
1122 | - element += (*i)->name(); |
1123 | - |
1124 | - element += (*i)->shortName(); |
1125 | - superset += QVariant(element); |
1126 | - } |
1127 | - |
1128 | - m_keyboardLayoutsModel.setSuperset(superset); |
1129 | - |
1130 | - enabledLayoutsChanged(); |
1131 | - |
1132 | - m_keyboardLayoutsModel.setAllowEmpty(false); |
1133 | - |
1134 | - connect(&m_keyboardLayoutsModel, |
1135 | - SIGNAL(subsetChanged()), SLOT(keyboardLayoutsModelChanged())); |
1136 | - |
1137 | - g_signal_connect(m_maliitSettings, "changed::" KEY_ENABLED_LAYOUTS, |
1138 | - G_CALLBACK(::enabledLayoutsChanged), this); |
1139 | -} |
1140 | |
1141 | void |
1142 | LanguagePlugin::updateSpellCheckingModel() |
1143 | @@ -573,41 +360,6 @@ |
1144 | plugin->managerLoaded(); |
1145 | } |
1146 | |
1147 | -void |
1148 | -LanguagePlugin::enabledLayoutsChanged() |
1149 | -{ |
1150 | - GVariantIter *iter; |
1151 | - const gchar *layout; |
1152 | - QList<int> subset; |
1153 | - |
1154 | - g_settings_get(m_maliitSettings, KEY_ENABLED_LAYOUTS, "as", &iter); |
1155 | - |
1156 | - while (g_variant_iter_next(iter, "&s", &layout)) { |
1157 | - for (int i(0); i < m_keyboardLayouts.length(); i++) { |
1158 | - if (m_keyboardLayouts[i]->name() == layout) { |
1159 | - subset += i; |
1160 | - break; |
1161 | - } |
1162 | - } |
1163 | - } |
1164 | - |
1165 | - g_variant_iter_free(iter); |
1166 | - |
1167 | - m_keyboardLayoutsModel.setSubset(subset); |
1168 | -} |
1169 | - |
1170 | -void |
1171 | -enabledLayoutsChanged(GSettings *settings, |
1172 | - gchar *key, |
1173 | - gpointer user_data) |
1174 | -{ |
1175 | - Q_UNUSED(settings); |
1176 | - Q_UNUSED(key); |
1177 | - |
1178 | - LanguagePlugin *plugin(static_cast<LanguagePlugin *>(user_data)); |
1179 | - plugin->enabledLayoutsChanged(); |
1180 | -} |
1181 | - |
1182 | void LanguagePlugin::reboot() |
1183 | { |
1184 | m_sessionService.reboot(); |
1185 | |
1186 | === modified file 'plugins/language/language-plugin.h' |
1187 | --- plugins/language/language-plugin.h 2015-04-10 11:22:10 +0000 |
1188 | +++ plugins/language/language-plugin.h 2016-03-14 14:37:14 +0000 |
1189 | @@ -56,10 +56,6 @@ |
1190 | WRITE setCurrentLanguage |
1191 | NOTIFY currentLanguageChanged) |
1192 | |
1193 | - Q_PROPERTY(SubsetModel *keyboardLayoutsModel |
1194 | - READ keyboardLayoutsModel |
1195 | - CONSTANT) |
1196 | - |
1197 | Q_PROPERTY(SubsetModel *spellCheckingModel |
1198 | READ spellCheckingModel |
1199 | CONSTANT) |
1200 | @@ -77,19 +73,15 @@ |
1201 | void setCurrentLanguage(int index); |
1202 | Q_SIGNAL void currentLanguageChanged() const; |
1203 | |
1204 | - SubsetModel *keyboardLayoutsModel(); |
1205 | - Q_SLOT void keyboardLayoutsModelChanged(); |
1206 | - |
1207 | SubsetModel *spellCheckingModel(); |
1208 | Q_SLOT void spellCheckingModelChanged(); |
1209 | |
1210 | + Q_INVOKABLE QString languageToLayout(const QString &lang); |
1211 | + |
1212 | private: |
1213 | |
1214 | void updateLanguageNamesAndCodes(); |
1215 | void updateCurrentLanguage(); |
1216 | - void updateEnabledLayouts(); |
1217 | - void updateKeyboardLayouts(); |
1218 | - void updateKeyboardLayoutsModel(); |
1219 | void updateSpellCheckingModel(); |
1220 | |
1221 | int indexForLocale(const QString &name); |
1222 | @@ -106,12 +98,6 @@ |
1223 | GParamSpec *pspec, |
1224 | gpointer user_data); |
1225 | |
1226 | - void enabledLayoutsChanged(); |
1227 | - |
1228 | - friend void enabledLayoutsChanged(GSettings *settings, |
1229 | - gchar *key, |
1230 | - gpointer user_data); |
1231 | - |
1232 | QStringList m_languageNames; |
1233 | QStringList m_languageCodes; |
1234 | QHash<QString, unsigned int> m_indicesByLocale; |
1235 | @@ -121,12 +107,8 @@ |
1236 | ActUserManager *m_manager; |
1237 | ActUser *m_user; |
1238 | |
1239 | - GSettings *m_maliitSettings; |
1240 | - QList<KeyboardLayout *> m_keyboardLayouts; |
1241 | - SubsetModel m_keyboardLayoutsModel; |
1242 | SubsetModel m_spellCheckingModel; |
1243 | SessionService m_sessionService; |
1244 | - QStringList m_layoutPaths; |
1245 | }; |
1246 | |
1247 | #endif // LANGUAGE_PLUGIN_H |
1248 | |
1249 | === added file 'plugins/language/onscreenkeyboard-plugin.cpp' |
1250 | --- plugins/language/onscreenkeyboard-plugin.cpp 1970-01-01 00:00:00 +0000 |
1251 | +++ plugins/language/onscreenkeyboard-plugin.cpp 2016-03-14 14:37:14 +0000 |
1252 | @@ -0,0 +1,294 @@ |
1253 | +/* |
1254 | + * This file is part of system-settings |
1255 | + * |
1256 | + * Copyright (C) 2015 Canonical Ltd. |
1257 | + * |
1258 | + * Contact: William Hua <william.hua@canonical.com> |
1259 | + * Jonas G. Drange <jonas.drange@canonical.com> |
1260 | + * |
1261 | + * This program is free software: you can redistribute it and/or modify it |
1262 | + * under the terms of the GNU General Public License version 3, as published |
1263 | + * by the Free Software Foundation. |
1264 | + * |
1265 | + * This program is distributed in the hope that it will be useful, but |
1266 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1267 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1268 | + * PURPOSE. See the GNU General Public License for more details. |
1269 | + * |
1270 | + * You should have received a copy of the GNU General Public License along |
1271 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1272 | + */ |
1273 | + |
1274 | +#include <QtDebug> |
1275 | +#include "onscreenkeyboard-plugin.h" |
1276 | + |
1277 | +#define UBUNTU_KEYBOARD_SCHEMA_ID "com.canonical.keyboard.maliit" |
1278 | + |
1279 | +#define KEY_ENABLED_LAYOUTS "enabled-languages" |
1280 | +#define KEY_CURRENT_LAYOUT "active-language" |
1281 | +#define KEY_PLUGIN_PATHS "plugin-paths" |
1282 | + |
1283 | +#define LAYOUTS_DIR "/usr/share/maliit/plugins/com/ubuntu/lib" |
1284 | + |
1285 | +OnScreenKeyboardPlugin::OnScreenKeyboardPlugin(QObject *parent) : |
1286 | + QObject(parent), |
1287 | + m_maliitSettings(g_settings_new(UBUNTU_KEYBOARD_SCHEMA_ID)) |
1288 | +{ |
1289 | + GVariantIter *iter; |
1290 | + const gchar *path; |
1291 | + |
1292 | + m_layoutPaths.append(LAYOUTS_DIR); |
1293 | + g_settings_get(m_maliitSettings, KEY_PLUGIN_PATHS, "as", &iter); |
1294 | + for (int i(0); g_variant_iter_next(iter, "&s", &path); i++) { |
1295 | + m_layoutPaths.append(path); |
1296 | + } |
1297 | + updateEnabledLayouts(); |
1298 | + updateKeyboardLayouts(); |
1299 | + updateKeyboardLayoutsModel(); |
1300 | +} |
1301 | + |
1302 | + |
1303 | +OnScreenKeyboardPlugin::~OnScreenKeyboardPlugin() |
1304 | +{ |
1305 | + if (m_maliitSettings != nullptr) { |
1306 | + g_signal_handlers_disconnect_by_data(m_maliitSettings, this); |
1307 | + g_object_unref(m_maliitSettings); |
1308 | + } |
1309 | + |
1310 | + for (QList<KeyboardLayout *>::const_iterator |
1311 | + i(m_keyboardLayouts.begin()); i != m_keyboardLayouts.end(); ++i) |
1312 | + delete *i; |
1313 | +} |
1314 | + |
1315 | +SubsetModel * |
1316 | +OnScreenKeyboardPlugin::keyboardLayoutsModel() |
1317 | +{ |
1318 | + return &m_keyboardLayoutsModel; |
1319 | +} |
1320 | + |
1321 | +void |
1322 | +OnScreenKeyboardPlugin::keyboardLayoutsModelChanged() |
1323 | +{ |
1324 | + GVariantBuilder builder; |
1325 | + gchar *current; |
1326 | + bool removed(true); |
1327 | + |
1328 | + g_variant_builder_init(&builder, G_VARIANT_TYPE("as")); |
1329 | + g_settings_get(m_maliitSettings, KEY_CURRENT_LAYOUT, "s", ¤t); |
1330 | + |
1331 | + for (QList<int>::const_iterator |
1332 | + i(m_keyboardLayoutsModel.subset().begin()); |
1333 | + i != m_keyboardLayoutsModel.subset().end(); ++i) { |
1334 | + g_variant_builder_add(&builder, "s", |
1335 | + qPrintable(m_keyboardLayouts[*i]->name())); |
1336 | + |
1337 | + if (m_keyboardLayouts[*i]->name() == current) |
1338 | + removed = false; |
1339 | + } |
1340 | + |
1341 | + if (removed && !m_keyboardLayoutsModel.subset().isEmpty()) { |
1342 | + GVariantIter *iter; |
1343 | + const gchar *layout; |
1344 | + bool found(false); |
1345 | + |
1346 | + g_settings_get(m_maliitSettings, KEY_ENABLED_LAYOUTS, "as", &iter); |
1347 | + |
1348 | + for (int i(0); g_variant_iter_next(iter, "&s", &layout); i++) { |
1349 | + found = g_strcmp0(layout, current) == 0; |
1350 | + |
1351 | + if (found) { |
1352 | + if (i >= m_keyboardLayoutsModel.subset().size()) |
1353 | + i = m_keyboardLayoutsModel.subset().size() - 1; |
1354 | + |
1355 | + int index(m_keyboardLayoutsModel.subset()[i]); |
1356 | + const QString &name(m_keyboardLayouts[index]->name()); |
1357 | + |
1358 | + g_settings_set_string(m_maliitSettings, |
1359 | + KEY_CURRENT_LAYOUT, qPrintable(name)); |
1360 | + |
1361 | + break; |
1362 | + } |
1363 | + } |
1364 | + |
1365 | + if (!found) { |
1366 | + int index(m_keyboardLayoutsModel.subset().front()); |
1367 | + const QString &name(m_keyboardLayouts[index]->name()); |
1368 | + |
1369 | + g_settings_set_string(m_maliitSettings, |
1370 | + KEY_CURRENT_LAYOUT, qPrintable(name)); |
1371 | + } |
1372 | + |
1373 | + g_variant_iter_free(iter); |
1374 | + } |
1375 | + |
1376 | + g_free(current); |
1377 | + g_settings_set_value(m_maliitSettings, |
1378 | + KEY_ENABLED_LAYOUTS, g_variant_builder_end(&builder)); |
1379 | +} |
1380 | + |
1381 | +static bool |
1382 | +compareLayouts(const KeyboardLayout *layout0, |
1383 | + const KeyboardLayout *layout1) |
1384 | +{ |
1385 | + QString name0(layout0->displayName()); |
1386 | + QString name1(layout1->displayName()); |
1387 | + |
1388 | + if (name0 == name1) { |
1389 | + name0 = layout0->language(); |
1390 | + name1 = layout1->language(); |
1391 | + |
1392 | + if (name0 == name1) { |
1393 | + name0 = layout0->name(); |
1394 | + name1 = layout1->name(); |
1395 | + } |
1396 | + } |
1397 | + |
1398 | + return QString::localeAwareCompare(name0, name1) < 0; |
1399 | +} |
1400 | + |
1401 | +void |
1402 | +OnScreenKeyboardPlugin::updateEnabledLayouts() |
1403 | +{ |
1404 | + GVariantBuilder builder; |
1405 | + GVariantIter *iter; |
1406 | + gchar *current; |
1407 | + const gchar *layout; |
1408 | + QSet<QString> added; |
1409 | + |
1410 | + g_variant_builder_init(&builder, G_VARIANT_TYPE("as")); |
1411 | + g_settings_get(m_maliitSettings, KEY_ENABLED_LAYOUTS, "as", &iter); |
1412 | + g_settings_get(m_maliitSettings, KEY_CURRENT_LAYOUT, "s", ¤t); |
1413 | + |
1414 | + while (g_variant_iter_next(iter, "&s", &layout)) { |
1415 | + if (!added.contains(layout)) { |
1416 | + g_variant_builder_add(&builder, "s", layout); |
1417 | + added.insert(layout); |
1418 | + } |
1419 | + } |
1420 | + |
1421 | + if (!added.contains(current)) { |
1422 | + g_variant_builder_add(&builder, "s", current); |
1423 | + added.insert(current); |
1424 | + } |
1425 | + |
1426 | + g_free(current); |
1427 | + g_variant_iter_free(iter); |
1428 | + g_settings_set_value(m_maliitSettings, |
1429 | + KEY_ENABLED_LAYOUTS, g_variant_builder_end(&builder)); |
1430 | +} |
1431 | + |
1432 | +void |
1433 | +OnScreenKeyboardPlugin::updateKeyboardLayouts() |
1434 | +{ |
1435 | + m_keyboardLayouts.clear(); |
1436 | + |
1437 | + for (int i = 0; i < m_layoutPaths.count(); i++) { |
1438 | + QDir layoutsDir(m_layoutPaths.at(i)); |
1439 | + layoutsDir.setFilter(QDir::Dirs); |
1440 | + layoutsDir.setSorting(QDir::Name); |
1441 | + |
1442 | + QFileInfoList fileInfoList(layoutsDir.entryInfoList()); |
1443 | + |
1444 | + for (QFileInfoList::const_iterator |
1445 | + i(fileInfoList.begin()); i != fileInfoList.end(); ++i) { |
1446 | + KeyboardLayout *layout(new KeyboardLayout(*i)); |
1447 | + |
1448 | + if (!layout->language().isEmpty()) |
1449 | + m_keyboardLayouts += layout; |
1450 | + else |
1451 | + delete layout; |
1452 | + } |
1453 | + } |
1454 | + |
1455 | + qSort(m_keyboardLayouts.begin(), m_keyboardLayouts.end(), compareLayouts); |
1456 | +} |
1457 | + |
1458 | +void enabledLayoutsChanged(GSettings *settings, |
1459 | + gchar *key, |
1460 | + gpointer user_data); |
1461 | + |
1462 | +void |
1463 | +OnScreenKeyboardPlugin::updateKeyboardLayoutsModel() |
1464 | +{ |
1465 | + QStringList customRoles; |
1466 | + customRoles += "language"; |
1467 | + customRoles += "icon"; |
1468 | + |
1469 | + m_keyboardLayoutsModel.setCustomRoles(customRoles); |
1470 | + |
1471 | + QVariantList superset; |
1472 | + |
1473 | + for (QList<KeyboardLayout *>::const_iterator |
1474 | + i(m_keyboardLayouts.begin()); i != m_keyboardLayouts.end(); ++i) { |
1475 | + QVariantList element; |
1476 | + |
1477 | + if (!(*i)->displayName().isEmpty()) |
1478 | + element += (*i)->displayName(); |
1479 | + else |
1480 | + element += (*i)->name(); |
1481 | + |
1482 | + element += (*i)->shortName(); |
1483 | + superset += QVariant(element); |
1484 | + } |
1485 | + |
1486 | + m_keyboardLayoutsModel.setSuperset(superset); |
1487 | + |
1488 | + enabledLayoutsChanged(); |
1489 | + |
1490 | + m_keyboardLayoutsModel.setAllowEmpty(false); |
1491 | + |
1492 | + connect(&m_keyboardLayoutsModel, |
1493 | + SIGNAL(subsetChanged()), SLOT(keyboardLayoutsModelChanged())); |
1494 | + |
1495 | + g_signal_connect(m_maliitSettings, "changed::" KEY_ENABLED_LAYOUTS, |
1496 | + G_CALLBACK(::enabledLayoutsChanged), this); |
1497 | +} |
1498 | + |
1499 | +void |
1500 | +OnScreenKeyboardPlugin::enabledLayoutsChanged() |
1501 | +{ |
1502 | + GVariantIter *iter; |
1503 | + const gchar *layout; |
1504 | + QList<int> subset; |
1505 | + |
1506 | + g_settings_get(m_maliitSettings, KEY_ENABLED_LAYOUTS, "as", &iter); |
1507 | + |
1508 | + while (g_variant_iter_next(iter, "&s", &layout)) { |
1509 | + for (int i(0); i < m_keyboardLayouts.length(); i++) { |
1510 | + if (m_keyboardLayouts[i]->name() == layout) { |
1511 | + subset += i; |
1512 | + break; |
1513 | + } |
1514 | + } |
1515 | + } |
1516 | + |
1517 | + g_variant_iter_free(iter); |
1518 | + |
1519 | + m_keyboardLayoutsModel.setSubset(subset); |
1520 | +} |
1521 | + |
1522 | +void |
1523 | +enabledLayoutsChanged(GSettings *settings, |
1524 | + gchar *key, |
1525 | + gpointer user_data) |
1526 | +{ |
1527 | + Q_UNUSED(settings); |
1528 | + Q_UNUSED(key); |
1529 | + |
1530 | + OnScreenKeyboardPlugin *plugin(static_cast<OnScreenKeyboardPlugin *>(user_data)); |
1531 | + plugin->enabledLayoutsChanged(); |
1532 | +} |
1533 | + |
1534 | +void OnScreenKeyboardPlugin::setCurrentLayout(const QString &code) |
1535 | +{ |
1536 | + for (int i = 0; i < m_layoutPaths.count(); i++) { |
1537 | + QFileInfo fileInfo(QDir(m_layoutPaths.at(i)), code); |
1538 | + |
1539 | + if (fileInfo.exists() && fileInfo.isDir()) { |
1540 | + g_settings_set_string(m_maliitSettings, |
1541 | + KEY_CURRENT_LAYOUT, code.toStdString().c_str()); |
1542 | + |
1543 | + updateEnabledLayouts(); |
1544 | + } |
1545 | + } |
1546 | +} |
1547 | |
1548 | === added file 'plugins/language/onscreenkeyboard-plugin.h' |
1549 | --- plugins/language/onscreenkeyboard-plugin.h 1970-01-01 00:00:00 +0000 |
1550 | +++ plugins/language/onscreenkeyboard-plugin.h 2016-03-14 14:37:14 +0000 |
1551 | @@ -0,0 +1,75 @@ |
1552 | +/* |
1553 | + * This file is part of system-settings |
1554 | + * |
1555 | + * Copyright (C) 2015 Canonical Ltd. |
1556 | + * |
1557 | + * Contact: William Hua <william.hua@canonical.com> |
1558 | + * Jonas G. Drange <jonas.drange@canonical.com> |
1559 | + * |
1560 | + * This program is free software: you can redistribute it and/or modify it |
1561 | + * under the terms of the GNU General Public License version 3, as published |
1562 | + * by the Free Software Foundation. |
1563 | + * |
1564 | + * This program is distributed in the hope that it will be useful, but |
1565 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1566 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1567 | + * PURPOSE. See the GNU General Public License for more details. |
1568 | + * |
1569 | + * You should have received a copy of the GNU General Public License along |
1570 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1571 | + */ |
1572 | + |
1573 | +#ifndef OSK_PLUGIN_H |
1574 | +#define OSK_PLUGIN_H |
1575 | + |
1576 | +#include <QtCore> |
1577 | +#include <gio/gio.h> |
1578 | +#include "subset-model.h" |
1579 | +#include "keyboard-layout.h" |
1580 | + |
1581 | +typedef struct _GSettings GSettings; |
1582 | +typedef void *gpointer; |
1583 | +typedef char gchar; |
1584 | + |
1585 | +class KeyboardLayout; |
1586 | + |
1587 | +class OnScreenKeyboardPlugin : public QObject |
1588 | +{ |
1589 | +private: |
1590 | + |
1591 | + Q_OBJECT |
1592 | + |
1593 | +public: |
1594 | + |
1595 | + Q_PROPERTY(SubsetModel *keyboardLayoutsModel |
1596 | + READ keyboardLayoutsModel |
1597 | + CONSTANT) |
1598 | + |
1599 | + explicit OnScreenKeyboardPlugin(QObject *parent = nullptr); |
1600 | + |
1601 | + virtual ~OnScreenKeyboardPlugin(); |
1602 | + |
1603 | + Q_INVOKABLE void setCurrentLayout(const QString &code); |
1604 | + |
1605 | + SubsetModel *keyboardLayoutsModel(); |
1606 | + Q_SLOT void keyboardLayoutsModelChanged(); |
1607 | + |
1608 | +private: |
1609 | + |
1610 | + void updateEnabledLayouts(); |
1611 | + void updateKeyboardLayouts(); |
1612 | + void updateKeyboardLayoutsModel(); |
1613 | + |
1614 | + void enabledLayoutsChanged(); |
1615 | + |
1616 | + friend void enabledLayoutsChanged(GSettings *settings, |
1617 | + gchar *key, |
1618 | + gpointer user_data); |
1619 | + |
1620 | + GSettings *m_maliitSettings; |
1621 | + QList<KeyboardLayout *> m_keyboardLayouts; |
1622 | + SubsetModel m_keyboardLayoutsModel; |
1623 | + QStringList m_layoutPaths; |
1624 | +}; |
1625 | + |
1626 | +#endif // OSK_PLUGIN_H |
1627 | |
1628 | === modified file 'plugins/language/plugin.cpp' |
1629 | --- plugins/language/plugin.cpp 2014-07-23 13:44:31 +0000 |
1630 | +++ plugins/language/plugin.cpp 2016-03-14 14:37:14 +0000 |
1631 | @@ -24,6 +24,8 @@ |
1632 | #include <QtQml> |
1633 | #include "subset-model.h" |
1634 | #include "language-plugin.h" |
1635 | +#include "onscreenkeyboard-plugin.h" |
1636 | +#include "hardwarekeyboard-plugin.h" |
1637 | |
1638 | void BackendPlugin::registerTypes(const char *uri) |
1639 | { |
1640 | @@ -31,6 +33,8 @@ |
1641 | |
1642 | qmlRegisterType<SubsetModel>(uri, 1, 0, "SubsetModel"); |
1643 | qmlRegisterType<LanguagePlugin>(uri, 1, 0, "UbuntuLanguagePlugin"); |
1644 | + qmlRegisterType<OnScreenKeyboardPlugin>(uri, 1, 0, "OnScreenKeyboardPlugin"); |
1645 | + qmlRegisterType<HardwareKeyboardPlugin>(uri, 1, 0, "HardwareKeyboardPlugin"); |
1646 | } |
1647 | |
1648 | void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
1649 | |
1650 | === modified file 'plugins/language/subset-model.cpp' |
1651 | --- plugins/language/subset-model.cpp 2014-01-27 17:05:24 +0000 |
1652 | +++ plugins/language/subset-model.cpp 2016-03-14 14:37:14 +0000 |
1653 | @@ -401,3 +401,27 @@ |
1654 | { |
1655 | return elementAtRow(index.row()); |
1656 | } |
1657 | + |
1658 | +void |
1659 | +SubsetModel::moveSubsetRow(int from, int to) { |
1660 | + // Make sure its not moved outside the lists |
1661 | + if (to < 0) { |
1662 | + to = 0; |
1663 | + } |
1664 | + if (to >= m_subset.count()) { |
1665 | + to = m_subset.count()-1; |
1666 | + } |
1667 | + |
1668 | + // Nothing to do? |
1669 | + if (from == to) { |
1670 | + return; |
1671 | + } |
1672 | + |
1673 | + // QList's and QAbstractItemModel's move implementation differ when moving an item up the list :/ |
1674 | + // While QList needs the index in the resulting list, beginMoveRows expects it to be in the current list |
1675 | + // adjust the model's index by +1 in case we're moving upwards |
1676 | + int newModelIndex = to > from ? to+1 : to; |
1677 | + beginMoveRows(QModelIndex(), from, from, QModelIndex(), newModelIndex); |
1678 | + m_subset.move(from, to); |
1679 | + endMoveRows(); |
1680 | +} |
1681 | |
1682 | === modified file 'plugins/language/subset-model.h' |
1683 | --- plugins/language/subset-model.h 2014-07-23 13:44:31 +0000 |
1684 | +++ plugins/language/subset-model.h 2016-03-14 14:37:14 +0000 |
1685 | @@ -65,6 +65,9 @@ |
1686 | virtual void setSubset(const QList<int> &subset); |
1687 | Q_SIGNAL virtual void subsetChanged() const; |
1688 | |
1689 | + virtual void moveSubsetRow(int from, int to); |
1690 | + |
1691 | + |
1692 | virtual bool allowEmpty() const; |
1693 | virtual void setAllowEmpty(bool allowEmpty); |
1694 | Q_SIGNAL virtual void allowEmptyChanged() const; |
1695 | |
1696 | === modified file 'tests/autopilot/ubuntu_system_settings/__init__.py' |
1697 | --- tests/autopilot/ubuntu_system_settings/__init__.py 2015-10-20 14:46:24 +0000 |
1698 | +++ tests/autopilot/ubuntu_system_settings/__init__.py 2016-03-14 14:37:14 +0000 |
1699 | @@ -1394,7 +1394,7 @@ |
1700 | @classmethod |
1701 | def validate_dbus_object(cls, path, state): |
1702 | name = introspection.get_classname_from_path(path) |
1703 | - if name == b'ItemPage': |
1704 | + if name == b'PageComponent': |
1705 | if state['objectName'][1] == 'languagePage': |
1706 | return True |
1707 | return False |
FAILED: Continuous integration, rev:1577 jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- ci/2559/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 5888/console jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- vivid-amd64- ci/334/ console jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- vivid-i386- ci/743/ console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 5899/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- system- settings- ci/2559/ rebuild
http://