on xenial help sign in
Bring navigation into the extra panel

Still lots of work to do

commit2caf749acac6ec0a24f0968fb9bbf546beac677f authorAlbert Astals Cid <albert.astals@canonical.com> dateTue 22 Sep 2015, 13:09 (11 years ago) parent85ff01f
7 files changed+186−282
qml/Dash/DashContent.qml+2−2 qml/Dash/DashNavigation.qml+138−39 qml/Dash/DashNavigationButton.qml−223 qml/Dash/DashNavigationList.qml−5 qml/Dash/GenericScopeView.qml+11−2 qml/Dash/PageHeader.qml+9−9 qml/Dash/PageHeaderExtraPanel.qml+26−2
qml/Dash/DashContent.qml+2−2
@@ -108,7 +108,7 @@ Item {
108108 objectName: "dashContentList"
109109
110110 interactive: !dashContent.forceNonInteractive && dashContent.scopes.loaded && currentItem
111− && !currentItem.moving && !currentItem.navigationDisableParentInteractive && !currentItem.subPageShown
111+ && !currentItem.moving && !currentItem.subPageShown && !currentItem.extraPanelShown
112112 anchors.fill: parent
113113 orientation: ListView.Horizontal
114114 boundsBehavior: Flickable.DragAndOvershootBounds
@@ -170,7 +170,7 @@ Item {
170170 objectName: "scopeLoader" + index
171171
172172 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
174174 readonly property bool subPageShown: item ? item.subPageShown : false
175175 readonly property var categoryView: item ? item.categoryView : null
176176 readonly property var theScope: scope
qml/Dash/DashNavigation.qml+138−39
@@ -17,71 +17,170 @@
1717import QtQuick 2.2
1818import Ubuntu.Components 1.1
1919import Dash 0.1
20−import "../Components"
2120
2221Item {
2322 id: root
2423 objectName: "dashNavigation"
2524
25+ // set by parent
2626 property var scope: null
2727 property var scopeStyle: null
28+ property real availableHeight
2829
29− property alias windowWidth: blackRect.width
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− }
30+ signal leafClicked()
3831
39− // FIXME this is only here for highlight purposes (see Background.qml, too)
40− readonly property var background: backgroundItem
32+ // internal
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
4136
4237 visible: height != 0
43− height: navigationButton.currentNavigation ? units.gu(5) : 0
38+ implicitHeight: navigationListView.y + navigationListView.height
4439
4540 QtObject {
4641 id: d
4742 readonly property color foregroundColor: root.scopeStyle
4843 ? root.scopeStyle.getTextColor(backgroundItem.luminance)
4944 : Theme.palette.normal.baseText
50− readonly property real navigationWidth: root.width >= units.gu(60) ? units.gu(40) : root.width
5145 }
5246
53− Rectangle {
54− id: blackRect
55− objectName: "blackRect"
56− color: "black"
57− opacity: openList && openList.currentItem && openList.currentItem.visible ? 0.5 : 0
58− Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
59− anchors { left: parent.left; right: parent.right }
60− visible: opacity > 0
47+ Label {
48+ id: label
49+ anchors.top: parent.top
50+ anchors.left: parent.left
51+ anchors.margins: units.gu(2)
52+ text: root.currentNavigation ? root.currentNavigation.label : ""
53+ color: d.foregroundColor
54+ elide: Text.ElideRight
55+ maximumLineCount: 1
6156 }
6257
63− Background {
64− id: backgroundItem
65− anchors.fill: parent
66− style: scopeStyle ? scopeStyle.navigationBackground : "color:///#f5f5f5"
58+ ListView {
59+ id: navigationListView
60+ objectName: "navigationListView"
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+ }
67154 }
68155
69156 Image {
157+ anchors {
158+ top: navigationListView.bottom
159+ left: navigationListView.left
160+ right: navigationListView.right
161+ }
70162 fillMode: Image.Stretch
71− source: scopeStyle.backgroundLuminance > 0.2 ? "graphics/navigation_shadow.png" : "graphics/navigation_shadow_light.png"
72− anchors { top: parent.bottom; left: parent.left; right: parent.right }
163+ source: "graphics/navigation_shadow.png"
73164 }
74165
75− DashNavigationButton {
76− id: navigationButton
77− objectName: "navigationButton"
78− height: root.height
79− width: d.navigationWidth
80− scope: root.scope
81− scopeStyle: root.scopeStyle
82− foregroundColor: d.foregroundColor
83− listView.width: d.navigationWidth
84− listView.x: -x
85− showDivider: root.width > d.navigationWidth
166+ property bool isFirstLoad: false
167+ onScopeChanged: {
168+ navigationModel.clear();
169+ isFirstLoad = true;
170+ }
171+ function setNewNavigation() {
172+ if (isFirstLoad && currentNavigation && currentNavigation.loaded) {
173+ isFirstLoad = false;
174+ if (currentNavigation.count > 0) {
175+ navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
176+ } else {
177+ navigationModel.append({"navigationId": currentNavigation.parentNavigationId, "nullifyNavigation": false});
178+ }
179+ }
180+ }
181+ Connections {
182+ target: currentNavigation
183+ onLoadedChanged: setNewNavigation();
86184 }
185+ onCurrentNavigationChanged: setNewNavigation();
87186}
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 {
3232 readonly property int itemHeight: units.gu(5)
3333 implicitHeight: flickable.contentHeight
3434
35− Background {
36− style: root.scopeStyle ? root.scopeStyle.navigationBackground : "color:///#f5f5f5"
37− anchors.fill: parent
38− }
39−
4035 clip: true
4136
4237 Behavior on height {
qml/Dash/GenericScopeView.qml+11−2
@@ -26,7 +26,6 @@ import "../Components/ListItems" as ListItems
2626FocusScope {
2727 id: scopeView
2828
29− readonly property bool navigationDisableParentInteractive: peExtraPanel.visible /*TODO bring back the dash navigation */
3029 property bool forceNonInteractive: false
3130 property var scope: null
3231 property UnitySortFilterProxyModel categories: categoryFilter
@@ -36,6 +35,7 @@ FocusScope {
3635 property bool enableHeightBehaviorOnNextCreation: false
3736 property var categoryView: categoryView
3837 readonly property alias subPageShown: subPageLoader.subPageShown
38+ readonly property alias extraPanelShown: peExtraPanel.visible
3939 property int paginationCount: 0
4040 property int paginationIndex: 0
4141 property bool visibleToParent: false
@@ -638,18 +638,27 @@ FocusScope {
638638
639639 PageHeaderExtraPanel {
640640 id: peExtraPanel
641− width: parent.width
641+ width: parent.width >= units.gu(60) ? units.gu(40) : parent.width
642642 anchors {
643643 top: categoryView.pageHeader.bottom
644644 topMargin: -categoryView.pageHeader.signatureLineHeight
645645 }
646646 z: 1
647647 visible: false
648+
648649 searchHistory: SearchHistoryModel
650+ scope: scopeView.scope
651+ scopeStyle: scopeView.scopeStyle
652+ windowHeight: scopeView.height
653+
649654 onHistoryItemClicked: {
650655 SearchHistoryModel.addQuery(text);
651656 categoryView.pageHeader.searchQuery = text;
652657 }
658+
659+ onDashNavigationLeafClicked: {
660+ categoryView.pageHeader.closePopup();
661+ }
653662 }
654663 }
655664
qml/Dash/PageHeader.qml+9−9
@@ -92,10 +92,10 @@ Item {
9292 }
9393 }
9494
95− function openSearchHistory() {
95+ function openPopup() {
9696 if (openSearchAnimation.running) {
97− openSearchAnimation.openSearchHistory = true;
98− } else if (root.searchHistory.count > 0) {
97+ openSearchAnimation.openPopup = true;
98+ } else if (extraPanel.hasContents) {
9999 // Show extraPanel
100100 extraPanel.visible = true;
101101 }
@@ -148,12 +148,12 @@ Item {
148148 Behavior on contentY {
149149 UbuntuNumberAnimation {
150150 id: openSearchAnimation
151− property bool openSearchHistory: false
151+ property bool openPopup: false
152152
153153 onRunningChanged: {
154− if (!running && openSearchAnimation.openSearchHistory) {
155− openSearchAnimation.openSearchHistory = false;
156− root.openSearchHistory();
154+ if (!running && openSearchAnimation.openPopup) {
155+ openSearchAnimation.openPopup = false;
156+ root.openPopup();
157157 }
158158 }
159159 }
@@ -218,14 +218,14 @@ Item {
218218
219219 onClicked: {
220220 root.resetSearch(true);
221− root.openSearchHistory();
221+ root.openPopup();
222222 }
223223 }
224224
225225 onActiveFocusChanged: {
226226 if (activeFocus) {
227227 root.searchTextFieldFocused();
228− root.openSearchHistory();
228+ root.openPopup();
229229 }
230230 }
231231
qml/Dash/PageHeaderExtraPanel.qml+26−2
@@ -21,11 +21,21 @@ import Ubuntu.Components.ListItems 1.0
2121Item {
2222 id: root
2323
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
2525
26+ implicitHeight: searchesHeight + dashNavigation.implicitHeight
27+
28+ // Set by parent
2629 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
2736
2837 signal historyItemClicked(string text)
38+ signal dashNavigationLeafClicked()
2939
3040 Rectangle {
3141 color: "white"
@@ -82,4 +92,18 @@ Item {
8292 }
8393 }
8494 }
85−}
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+ }
109+}