@@ -20,6 +20,7 @@ import Unity.Launcher 0.1
20import Utils 0.1
20import Utils 0.1
21import "../Components"
21import "../Components"
22import Qt.labs.settings 1.0
22import Qt.labs.settings 1.0
24FocusScope {
25FocusScope {
@@ -43,6 +44,12 @@ FocusScope {
43 searchField.focus = true;
44 searchField.focus = true;
48+ // Catch all presses here in case the navigation lets something through
49+ // We never want to end up in the launcher with focus
50+ event.accepted = true;
46 Settings {
53 Settings {
47 property alias selectedTab: sections.selectedIndex
54 property alias selectedTab: sections.selectedIndex
@@ -79,6 +86,9 @@ FocusScope {
79 anchors { left: parent.left; top: parent.top; right: parent.right; margins: units.gu(1) }
86 anchors { left: parent.left; top: parent.top; right: parent.right; margins: units.gu(1) }
80 placeholderText: i18n.tr("Search…")
87 placeholderText: i18n.tr("Search…")
81 focus: true
88 focus: true
90+ KeyNavigation.down: sections
82 onAccepted: {
92 onAccepted: {
83 if (searchField.displayText != "" && listLoader.item && listLoader.item.currentItem) {
93 if (searchField.displayText != "" && listLoader.item && listLoader.item.currentItem) {
84 root.applicationSelected(listLoader.item.getFirstAppId());
94 root.applicationSelected(listLoader.item.getFirstAppId());
@@ -96,13 +106,19 @@ FocusScope {
96 Sections {
106 Sections {
97 id: sections
107 id: sections
98 width: parent.width
108 width: parent.width
110+ KeyNavigation.up: searchField
111+ KeyNavigation.down: headerFocusScope
112+ KeyNavigation.backtab: searchField
113+ KeyNavigation.tab: headerFocusScope
99 actions: [
115 actions: [
101 text: i18n.ctr("Apps sorted alphabetically", "A-Z")
117 text: i18n.ctr("Apps sorted alphabetically", "A-Z")
102 // TODO: Disabling this for now as we don't get the right input from u-a-l yet.
118 // TODO: Disabling this for now as we don't get the right input from u-a-l yet.
104−// Action {
120+ Action {
105−// text: i18n.ctr("Most used apps", "Most used")
121+ text: i18n.ctr("Most used apps", "Most used")
@@ -115,9 +131,42 @@ FocusScope {
135+ id: headerFocusScope
136+ KeyNavigation.up: sections
137+ KeyNavigation.down: listLoader.item
138+ KeyNavigation.backtab: sections
139+ KeyNavigation.tab: listLoader.item
143+ schema.id: "com.canonical.Unity8"
147+ switch (event.key) {
152+ event.accepted = true;
156+ function trigger() {
157+ Qt.openUrlExternally(settings.appstoreUri)
119 id: listLoader
162 id: listLoader
120 anchors { left: parent.left; top: sectionsContainer.bottom; right: parent.right; bottom: parent.bottom; leftMargin: units.gu(1); rightMargin: units.gu(1) }
163 anchors { left: parent.left; top: sectionsContainer.bottom; right: parent.right; bottom: parent.bottom; leftMargin: units.gu(1); rightMargin: units.gu(1) }
165+ KeyNavigation.up: headerFocusScope
166+ KeyNavigation.down: searchField
167+ KeyNavigation.backtab: headerFocusScope
168+ KeyNavigation.tab: searchField
121 sourceComponent: {
170 sourceComponent: {
122 switch (sections.selectedIndex) {
171 switch (sections.selectedIndex) {
123 case 0: return aToZComponent;
172 case 0: return aToZComponent;
@@ -167,10 +216,13 @@ FocusScope {
167 Component {
216 Component {
168 id: mostUsedComponent
217 id: mostUsedComponent
169 DrawerListView {
218 DrawerListView {
219+ id: mostUsedListView
171 header: MoreAppsHeader {
221 header: MoreAppsHeader {
172 width: parent.width
222 width: parent.width
173 height: units.gu(6)
223 height: units.gu(6)
224+ highlighted: headerFocusScope.activeFocus
225+ onClicked: headerFocusScope.trigger();
176 model: AppDrawerProxyModel {
228 model: AppDrawerProxyModel {
@@ -196,6 +248,9 @@ FocusScope {
196 bottomMargin: units.gu(1)
248 bottomMargin: units.gu(1)
197 clip: true
249 clip: true
252+ focus: index == mostUsedListView.currentIndex
199 model: sortProxyModel
254 model: sortProxyModel
201 delegateWidth: units.gu(8)
256 delegateWidth: units.gu(8)
@@ -209,10 +264,13 @@ FocusScope {
209 Component {
264 Component {
210 id: aToZComponent
265 id: aToZComponent
211 DrawerListView {
266 DrawerListView {
213 header: MoreAppsHeader {
269 header: MoreAppsHeader {
214 width: parent.width
270 width: parent.width
215 height: units.gu(6)
271 height: units.gu(6)
272+ highlighted: headerFocusScope.activeFocus
273+ onClicked: headerFocusScope.trigger();
218 model: AppDrawerProxyModel {
276 model: AppDrawerProxyModel {
@@ -244,7 +302,11 @@ FocusScope {
244 anchors { left: parent.left; top: categoryNameLabel.bottom; right: parent.right; topMargin: units.gu(1) }
302 anchors { left: parent.left; top: categoryNameLabel.bottom; right: parent.right; topMargin: units.gu(1) }
245 height: rows * delegateHeight
303 height: rows * delegateHeight
247− interactive: false
305+ interactive: true
306+ focus: index == aToZListView.currentIndex
307+ onFocusChanged: print("drawer grid", index, "has focus", focus)
309+ onCurrentIndexChanged: print("grid currentIndex changed", currentIndex)
249 model: AppDrawerProxyModel {
311 model: AppDrawerProxyModel {
250 id: categoryModel
312 id: categoryModel
@@ -263,10 +325,13 @@ FocusScope {
263 Component {
325 Component {
264 id: drawerDelegateComponent
326 id: drawerDelegateComponent
265 AbstractButton {
327 AbstractButton {
266 width: GridView.view.cellWidth
329 width: GridView.view.cellWidth
267 height: units.gu(10)
330 height: units.gu(10)
268 objectName: "drawerItem_" + model.appId
331 objectName: "drawerItem_" + model.appId
333+ property bool focused: index === GridView.view.currentIndex && GridView.view.activeFocus
270 onClicked: root.applicationSelected(model.appId)
335 onClicked: root.applicationSelected(model.appId)
@@ -290,6 +355,17 @@ FocusScope {
290 source: model.icon
355 source: model.icon
292 sourceFillMode: UbuntuShape.PreserveAspectCrop
357 sourceFillMode: UbuntuShape.PreserveAspectCrop
360+ objectName: "focusRing"
361+ anchors.centerIn: parent
362+ height: width * 15 / 16
363+ width: parent.width + units.gu(1)
364+ source: "graphics/launcher-app-focus-ring.svg"
365+ sourceSize.width: width
366+ sourceSize.height: height
367+ visible: drawerDelegate.focused