on xenial help sign in
Bring navigation into the extra panel
2caf749Albert Astals Cid
qml/Dash/DashContent.qml+2−2
@@ -108,7 +108,7 @@ Item {
108 objectName: "dashContentList"
108 objectName: "dashContentList"
109
109
110 interactive: !dashContent.forceNonInteractive && dashContent.scopes.loaded && currentItem
110 interactive: !dashContent.forceNonInteractive && dashContent.scopes.loaded && currentItem
111− && !currentItem.moving && !currentItem.navigationDisableParentInteractive && !currentItem.subPageShown
111+ && !currentItem.moving && !currentItem.subPageShown && !currentItem.extraPanelShown
112 anchors.fill: parent
112 anchors.fill: parent
113 orientation: ListView.Horizontal
113 orientation: ListView.Horizontal
114 boundsBehavior: Flickable.DragAndOvershootBounds
114 boundsBehavior: Flickable.DragAndOvershootBounds
@@ -170,7 +170,7 @@ Item {
170 objectName: "scopeLoader" + index
170 objectName: "scopeLoader" + index
171
171
172 readonly property bool moving: item ? item.moving : false
172 readonly property bool moving: item ? item.moving : false
173− readonly property bool navigationDisableParentInteractive: item ? item.navigationDisableParentInteractive : false
173+ readonly property bool extraPanelShown: item ? item.extraPanelShown : false
174 readonly property bool subPageShown: item ? item.subPageShown : false
174 readonly property bool subPageShown: item ? item.subPageShown : false
175 readonly property var categoryView: item ? item.categoryView : null
175 readonly property var categoryView: item ? item.categoryView : null
176 readonly property var theScope: scope
176 readonly property var theScope: scope
qml/Dash/DashNavigation.qml+138−39
@@ -17,71 +17,170 @@
17import QtQuick 2.2
17import QtQuick 2.2
18import Ubuntu.Components 1.1
18import Ubuntu.Components 1.1
19import Dash 0.1
19import Dash 0.1
20−import "../Components"
21
20
22Item {
21Item {
23 id: root
22 id: root
24 objectName: "dashNavigation"
23 objectName: "dashNavigation"
25
24
25+ // set by parent
26 property var scope: null
26 property var scope: null
27 property var scopeStyle: null
27 property var scopeStyle: null
28+ property real availableHeight
28
29
29− property alias windowWidth: blackRect.width
30+ signal leafClicked()
30− property alias windowHeight: blackRect.height
31− readonly property var openList: {
32− if (navigationButton.showList) return navigationButton.listView;
33− return null;
34− }
35− readonly property bool disableParentInteractive: {
36− return navigationButton.showList || navigationButton.inverseMousePressed;
37− }
38
31
39− // FIXME this is only here for highlight purposes (see Background.qml, too)
32+ // internal
40− readonly property var background: backgroundItem
33+ readonly property var currentNavigation: scope && scope.hasNavigation ? scope.getNavigation(scope.currentNavigationId) : null
34+ // Are we drilling down the tree or up?
35+ property bool isGoingBack: false
41
36
42 visible: height != 0
37 visible: height != 0
43− height: navigationButton.currentNavigation ? units.gu(5) : 0
38+ implicitHeight: navigationListView.y + navigationListView.height
44
39
45 QtObject {
40 QtObject {
46 id: d
41 id: d
47 readonly property color foregroundColor: root.scopeStyle
42 readonly property color foregroundColor: root.scopeStyle
48 ? root.scopeStyle.getTextColor(backgroundItem.luminance)
43 ? root.scopeStyle.getTextColor(backgroundItem.luminance)
49 : Theme.palette.normal.baseText
44 : Theme.palette.normal.baseText
50− readonly property real navigationWidth: root.width >= units.gu(60) ? units.gu(40) : root.width
51 }
45 }
52
46
53− Rectangle {
47+ Label {
54− id: blackRect
48+ id: label
55− objectName: "blackRect"
49+ anchors.top: parent.top
56− color: "black"
50+ anchors.left: parent.left
57− opacity: openList && openList.currentItem && openList.currentItem.visible ? 0.5 : 0
51+ anchors.margins: units.gu(2)
58− Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
52+ text: root.currentNavigation ? root.currentNavigation.label : ""
59− anchors { left: parent.left; right: parent.right }
53+ color: d.foregroundColor
60− visible: opacity > 0
54+ elide: Text.ElideRight
55+ maximumLineCount: 1
61 }
56 }
62
57
63− Background {
58+ ListView {
64− id: backgroundItem
59+ id: navigationListView
65− anchors.fill: parent
60+ objectName: "navigationListView"
66− style: scopeStyle ? scopeStyle.navigationBackground : "color:///#f5f5f5"
61+ orientation: ListView.Horizontal
62+ interactive: false
63+ model: ListModel {
64+ id: navigationModel
65+ // We have two roles
66+ // navigationId: the navigation id of the navigation the list represents
67+ // nullifyNavigation: overrides navigationId to be null
68+ // This is used to "clear" the delegate when going "right" on the tree
69+ }
70+ anchors.top: label.bottom
71+ property int maxHeight: -1
72+ Component.onCompleted: updateMaxHeight();
73+ function updateMaxHeight()
74+ {
75+ maxHeight = root.availableHeight - mapToItem(root, 0, 0).y;
76+ }
77+ property int prevHeight: maxHeight
78+ height: currentItem ? currentItem.height : maxHeight
79+ width: parent.width
80+
81+ onHeightChanged: {
82+ if (currentItem) {
83+ prevHeight = currentItem.desiredHeight;
84+ }
85+ }
86+ highlightMoveDuration: UbuntuAnimation.FastDuration
87+ delegate: DashNavigationList {
88+ objectName: "navigation" + index
89+ visible: height > 0
90+ width: navigationListView.width
91+ scopeStyle: root.scopeStyle
92+ foregroundColor: d.foregroundColor
93+ property real desiredHeight: {
94+ if (navigation && navigation.loaded && x == navigationListView.contentX)
95+ {
96+ navigationListView.updateMaxHeight();
97+ return Math.min(implicitHeight, navigationListView.maxHeight);
98+ } else {
99+ return navigationListView.prevHeight;
100+ }
101+ }
102+ height: desiredHeight
103+ navigation: (nullifyNavigation || !scope) ? null : scope.getNavigation(navigationId)
104+ currentNavigation: root.currentNavigation
105+ onEnterNavigation: {
106+ scope.setNavigationState(newNavigationId);
107+ // We only need to add a new item to the model
108+ // if we have children, otherwise just load it
109+ if (hasChildren) {
110+ isGoingBack = false;
111+ navigationModel.append({"navigationId": newNavigationId, "nullifyNavigation": false});
112+ navigationListView.currentIndex++;
113+ } else {
114+ root.leafClicked();
115+ }
116+ }
117+ onGoBackToParentClicked: {
118+ if (navigationListView.currentIndex == 0) {
119+ // This can happen if we jumped to the non root of a deep tree and the user
120+ // is now going back, create space in the list for the list to move "left"
121+ var aux = navigationListView.highlightMoveDuration;
122+ navigationListView.highlightMoveDuration = 0;
123+ navigationModel.insert(0, {"navigationId": navigation.parentNavigationId, "nullifyNavigation": false});
124+ navigationListView.currentIndex = navigationListView.currentIndex + 1;
125+ navigationListView.contentX = width * navigationListView.currentIndex;
126+ navigationListView.highlightMoveDuration = aux;
127+ }
128+
129+ scope.setNavigationState(navigation.parentNavigationId);
130+ isGoingBack = true;
131+ navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", false);
132+ navigationListView.currentIndex--;
133+ }
134+ onAllNavigationClicked: {
135+ root.leafClicked();
136+ if (root.currentNavigation.parentNavigationId == navigation.navigationId) {
137+ // For leaves we have to go to the parent too
138+ scope.setNavigationState(root.currentNavigation.parentNavigationId);
139+ }
140+ }
141+ }
142+ onContentXChanged: {
143+ if (navigationListView.highlightMoveDuration == 0)
144+ return;
145+
146+ if (contentX == width * navigationListView.currentIndex) {
147+ if (isGoingBack) {
148+ navigationModel.remove(navigationListView.currentIndex + 1);
149+ } else {
150+ navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", true);
151+ }
152+ }
153+ }
67 }
154 }
68
155
69 Image {
156 Image {
157+ anchors {
158+ top: navigationListView.bottom
159+ left: navigationListView.left
160+ right: navigationListView.right
161+ }
70 fillMode: Image.Stretch
162 fillMode: Image.Stretch
71− source: scopeStyle.backgroundLuminance > 0.2 ? "graphics/navigation_shadow.png" : "graphics/navigation_shadow_light.png"
163+ source: "graphics/navigation_shadow.png"
72− anchors { top: parent.bottom; left: parent.left; right: parent.right }
73 }
164 }
74
165
75− DashNavigationButton {
166+ property bool isFirstLoad: false
76− id: navigationButton
167+ onScopeChanged: {
77− objectName: "navigationButton"
168+ navigationModel.clear();
78− height: root.height
169+ isFirstLoad = true;
79− width: d.navigationWidth
170+ }
80− scope: root.scope
171+ function setNewNavigation() {
81− scopeStyle: root.scopeStyle
172+ if (isFirstLoad && currentNavigation && currentNavigation.loaded) {
82− foregroundColor: d.foregroundColor
173+ isFirstLoad = false;
83− listView.width: d.navigationWidth
174+ if (currentNavigation.count > 0) {
84− listView.x: -x
175+ navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
85− showDivider: root.width > d.navigationWidth
176+ } else {
177+ navigationModel.append({"navigationId": currentNavigation.parentNavigationId, "nullifyNavigation": false});
178+ }
179+ }
180+ }
181+ Connections {
182+ target: currentNavigation
183+ onLoadedChanged: setNewNavigation();
86 }
184 }
185+ onCurrentNavigationChanged: setNewNavigation();
87}
186}
qml/Dash/DashNavigationButton.qmldeleted−223
@@ -1,223 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.2
18−import Ubuntu.Components 1.1
19−
20−AbstractButton {
21− id: root
22− objectName: "dashNavigation"
23−
24− // Set by parent
25− property var scope: null
26− property var scopeStyle: null
27− property color foregroundColor: Theme.palette.normal.baseText
28− property bool showDivider: false
29−
30− // Used by parent
31− readonly property var currentNavigation: scope && scope.hasNavigation ? scope.getNavigation(scope.currentNavigationId) : null
32− readonly property alias listView: navigationListView
33− readonly property bool inverseMousePressed: inverseMouseArea.pressed
34− property bool showList: false
35−
36− // Internal
37− // Are we drilling down the tree or up?
38− property bool isGoingBack: false
39−
40− visible: root.currentNavigation != null
41−
42− onClicked: {
43− navigationListView.updateMaxHeight();
44− root.showList = !root.showList;
45− }
46−
47− Label {
48− anchors.fill: parent
49− anchors.margins: units.gu(2)
50− anchors.rightMargin: units.gu(5)
51− verticalAlignment: Text.AlignVCenter
52− text: root.currentNavigation ? root.currentNavigation.label : ""
53− color: root.foregroundColor
54− elide: Text.ElideRight
55− maximumLineCount: 1
56− }
57−
58− Icon {
59− anchors.verticalCenter: parent.verticalCenter
60− anchors.right: parent.right
61− anchors.rightMargin: units.gu(2)
62− name: showList ? "up" : "down"
63− height: units.gu(2)
64− width: height
65− color: root.foregroundColor
66− }
67−
68− // navigationListView is outside root
69− ListView {
70− id: navigationListView
71− objectName: "navigationListView"
72− visible: height > 0
73− orientation: ListView.Horizontal
74− interactive: false
75− clip: root.width != windowWidth
76− model: ListModel {
77− id: navigationModel
78− // We have two roles
79− // navigationId: the navigation id of the navigation the list represents
80− // nullifyNavigation: overrides navigationId to be null
81− // This is used to "clear" the delegate when going "right" on the tree
82− }
83− anchors.top: root.bottom
84− property int maxHeight: -1
85− Component.onCompleted: updateMaxHeight();
86− function updateMaxHeight()
87− {
88− maxHeight = (windowHeight - mapToItem(null, 0, 0).y) - units.gu(8);
89− }
90− property int prevHeight: maxHeight
91− height: currentItem ? currentItem.height : maxHeight
92− onHeightChanged: {
93− if (root.showList) {
94− prevHeight = currentItem.desiredHeight;
95− }
96− }
97− highlightMoveDuration: UbuntuAnimation.FastDuration
98− delegate: DashNavigationList {
99− objectName: "navigation" + index
100− visible: height > 0
101− width: navigationListView.width
102− scopeStyle: root.scopeStyle
103− foregroundColor: root.foregroundColor
104− property real desiredHeight: {
105− if (root.showList) {
106− if (navigation && navigation.loaded && x == navigationListView.contentX)
107− {
108− navigationListView.updateMaxHeight();
109− return Math.min(implicitHeight, navigationListView.maxHeight);
110− } else {
111− return navigationListView.prevHeight;
112− }
113− } else {
114− return 0;
115− }
116− }
117− height: desiredHeight
118− navigation: (nullifyNavigation || !scope) ? null : scope.getNavigation(navigationId)
119− currentNavigation: root.currentNavigation
120− onEnterNavigation: {
121− scope.setNavigationState(newNavigationId);
122− // We only need to add a new item to the model
123− // if we have children, otherwise just load it
124− if (hasChildren) {
125− isGoingBack = false;
126− navigationModel.append({"navigationId": newNavigationId, "nullifyNavigation": false});
127− navigationListView.currentIndex++;
128− } else {
129− showList = false;
130− }
131− }
132− onGoBackToParentClicked: {
133− if (navigationListView.currentIndex == 0) {
134− // This can happen if we jumped to the non root of a deep tree and the user
135− // is now going back, create space in the list for the list to move "left"
136− var aux = navigationListView.highlightMoveDuration;
137− navigationListView.highlightMoveDuration = 0;
138− navigationModel.insert(0, {"navigationId": navigation.parentNavigationId, "nullifyNavigation": false});
139− navigationListView.currentIndex = navigationListView.currentIndex + 1;
140− navigationListView.contentX = width * navigationListView.currentIndex;
141− navigationListView.highlightMoveDuration = aux;
142− }
143−
144− scope.setNavigationState(navigation.parentNavigationId);
145− isGoingBack = true;
146− navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", false);
147− navigationListView.currentIndex--;
148− }
149− onAllNavigationClicked: {
150− showList = false;
151− if (root.currentNavigation.parentNavigationId == navigation.navigationId) {
152− // For leaves we have to go to the parent too
153− scope.setNavigationState(root.currentNavigation.parentNavigationId);
154− }
155− }
156− }
157− onContentXChanged: {
158− if (navigationListView.highlightMoveDuration == 0)
159− return;
160−
161− if (contentX == width * navigationListView.currentIndex) {
162− if (isGoingBack) {
163− navigationModel.remove(navigationListView.currentIndex + 1);
164− } else {
165− navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", true);
166− }
167− }
168− }
169− }
170−
171− Image {
172− anchors {
173− top: navigationListView.bottom
174− left: navigationListView.left
175− right: navigationListView.right
176− }
177− fillMode: Image.Stretch
178− source: "graphics/navigation_shadow.png"
179− visible: root.showList
180− }
181−
182− property bool isFirstLoad: false
183− onScopeChanged: {
184− navigationModel.clear();
185− isFirstLoad = true;
186− }
187− function setNewNavigation() {
188− if (isFirstLoad && currentNavigation && currentNavigation.loaded) {
189− isFirstLoad = false;
190− if (currentNavigation.count > 0) {
191− navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
192− } else {
193− navigationModel.append({"navigationId": currentNavigation.parentNavigationId, "nullifyNavigation": false});
194− }
195− }
196− }
197− Connections {
198− target: currentNavigation
199− onLoadedChanged: setNewNavigation();
200− }
201− onCurrentNavigationChanged: setNewNavigation();
202−
203− InverseMouseArea {
204− id: inverseMouseArea
205− anchors.fill: navigationListView
206− enabled: root.showList
207− onPressed: root.showList = false
208− }
209−
210− Rectangle {
211− visible: root.showDivider
212− anchors {
213− top: parent.top
214− topMargin: units.dp(1)
215− bottom: parent.bottom
216− left: parent.right
217− leftMargin: -units.dp(0.5)
218− }
219− width: units.dp(1)
220− color: root.foregroundColor
221− opacity: 0.2
222− }
223−}
qml/Dash/DashNavigationList.qml−5
@@ -32,11 +32,6 @@ Item {
32 readonly property int itemHeight: units.gu(5)
32 readonly property int itemHeight: units.gu(5)
33 implicitHeight: flickable.contentHeight
33 implicitHeight: flickable.contentHeight
34
34
35− Background {
36− style: root.scopeStyle ? root.scopeStyle.navigationBackground : "color:///#f5f5f5"
37− anchors.fill: parent
38− }
39−
40 clip: true
35 clip: true
41
36
42 Behavior on height {
37 Behavior on height {
qml/Dash/GenericScopeView.qml+11−2
@@ -26,7 +26,6 @@ import "../Components/ListItems" as ListItems
26FocusScope {
26FocusScope {
27 id: scopeView
27 id: scopeView
28
28
29− readonly property bool navigationDisableParentInteractive: peExtraPanel.visible /*TODO bring back the dash navigation */
30 property bool forceNonInteractive: false
29 property bool forceNonInteractive: false
31 property var scope: null
30 property var scope: null
32 property UnitySortFilterProxyModel categories: categoryFilter
31 property UnitySortFilterProxyModel categories: categoryFilter
@@ -36,6 +35,7 @@ FocusScope {
36 property bool enableHeightBehaviorOnNextCreation: false
35 property bool enableHeightBehaviorOnNextCreation: false
37 property var categoryView: categoryView
36 property var categoryView: categoryView
38 readonly property alias subPageShown: subPageLoader.subPageShown
37 readonly property alias subPageShown: subPageLoader.subPageShown
38+ readonly property alias extraPanelShown: peExtraPanel.visible
39 property int paginationCount: 0
39 property int paginationCount: 0
40 property int paginationIndex: 0
40 property int paginationIndex: 0
41 property bool visibleToParent: false
41 property bool visibleToParent: false
@@ -638,18 +638,27 @@ FocusScope {
638
638
639 PageHeaderExtraPanel {
639 PageHeaderExtraPanel {
640 id: peExtraPanel
640 id: peExtraPanel
641− width: parent.width
641+ width: parent.width >= units.gu(60) ? units.gu(40) : parent.width
642 anchors {
642 anchors {
643 top: categoryView.pageHeader.bottom
643 top: categoryView.pageHeader.bottom
644 topMargin: -categoryView.pageHeader.signatureLineHeight
644 topMargin: -categoryView.pageHeader.signatureLineHeight
645 }
645 }
646 z: 1
646 z: 1
647 visible: false
647 visible: false
648+
648 searchHistory: SearchHistoryModel
649 searchHistory: SearchHistoryModel
650+ scope: scopeView.scope
651+ scopeStyle: scopeView.scopeStyle
652+ windowHeight: scopeView.height
653+
649 onHistoryItemClicked: {
654 onHistoryItemClicked: {
650 SearchHistoryModel.addQuery(text);
655 SearchHistoryModel.addQuery(text);
651 categoryView.pageHeader.searchQuery = text;
656 categoryView.pageHeader.searchQuery = text;
652 }
657 }
658+
659+ onDashNavigationLeafClicked: {
660+ categoryView.pageHeader.closePopup();
661+ }
653 }
662 }
654 }
663 }
655
664
qml/Dash/PageHeader.qml+9−9
@@ -92,10 +92,10 @@ Item {
92 }
92 }
93 }
93 }
94
94
95− function openSearchHistory() {
95+ function openPopup() {
96 if (openSearchAnimation.running) {
96 if (openSearchAnimation.running) {
97− openSearchAnimation.openSearchHistory = true;
97+ openSearchAnimation.openPopup = true;
98− } else if (root.searchHistory.count > 0) {
98+ } else if (extraPanel.hasContents) {
99 // Show extraPanel
99 // Show extraPanel
100 extraPanel.visible = true;
100 extraPanel.visible = true;
101 }
101 }
@@ -148,12 +148,12 @@ Item {
148 Behavior on contentY {
148 Behavior on contentY {
149 UbuntuNumberAnimation {
149 UbuntuNumberAnimation {
150 id: openSearchAnimation
150 id: openSearchAnimation
151− property bool openSearchHistory: false
151+ property bool openPopup: false
152
152
153 onRunningChanged: {
153 onRunningChanged: {
154− if (!running && openSearchAnimation.openSearchHistory) {
154+ if (!running && openSearchAnimation.openPopup) {
155− openSearchAnimation.openSearchHistory = false;
155+ openSearchAnimation.openPopup = false;
156− root.openSearchHistory();
156+ root.openPopup();
157 }
157 }
158 }
158 }
159 }
159 }
@@ -218,14 +218,14 @@ Item {
218
218
219 onClicked: {
219 onClicked: {
220 root.resetSearch(true);
220 root.resetSearch(true);
221− root.openSearchHistory();
221+ root.openPopup();
222 }
222 }
223 }
223 }
224
224
225 onActiveFocusChanged: {
225 onActiveFocusChanged: {
226 if (activeFocus) {
226 if (activeFocus) {
227 root.searchTextFieldFocused();
227 root.searchTextFieldFocused();
228− root.openSearchHistory();
228+ root.openPopup();
229 }
229 }
230 }
230 }
231
231
qml/Dash/PageHeaderExtraPanel.qml+26−2
@@ -21,11 +21,21 @@ import Ubuntu.Components.ListItems 1.0
21Item {
21Item {
22 id: root
22 id: root
23
23
24− implicitHeight: recentSearchesRepeater.count > 0 ? searchColumn.height + recentSearchesLabels.height + recentSearchesLabels.anchors.margins : 0
24+ readonly property real searchesHeight: recentSearchesRepeater.count > 0 ? searchColumn.height + recentSearchesLabels.height + recentSearchesLabels.anchors.margins : 0
25
25
26+ implicitHeight: searchesHeight + dashNavigation.implicitHeight
27+
28+ // Set by parent
26 property ListModel searchHistory
29 property ListModel searchHistory
30+ property var scope: null
31+ property var scopeStyle: null
32+ property real windowHeight
33+
34+ // Used by PageHeader
35+ readonly property bool hasContents: searchHistory.count > 0 || scope && scope.hasNavigation
27
36
28 signal historyItemClicked(string text)
37 signal historyItemClicked(string text)
38+ signal dashNavigationLeafClicked()
29
39
30 Rectangle {
40 Rectangle {
31 color: "white"
41 color: "white"
@@ -82,4 +92,18 @@ Item {
82 }
92 }
83 }
93 }
84 }
94 }
95+
96+ DashNavigation {
97+ id: dashNavigation
98+ scope: root.scope
99+ anchors {
100+ top: recentSearchesRepeater.count > 0 ? searchColumn.bottom : parent.top
101+ left: parent.left
102+ right: parent.right
103+ }
104+ scopeStyle: root.scopeStyle
105+ availableHeight: windowHeight * 4 / 6 - searchesHeight
106+
107+ onLeafClicked: root.dashNavigationLeafClicked();
108+ }
85−}
109+}