Lomiri
Loading...
Searching...
No Matches
PanelMenuPage.qml
1/*
2 * Copyright 2013-2016 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.12
18import Lomiri.Components 1.3
19import Lomiri.Components.ListItems 1.3 as ListItems
20import Lomiri.Indicators 0.1 as Indicators
21import "../Components"
22import "Indicators"
23
24PageStack {
25 id: root
26
27 property var submenuIndex: undefined
28 property QtObject menuModel: null
29 property Component factory
30
31 Connections {
32 id: dynamicChanges
33 target: root.menuModel
34 property bool ready: false
35
36 // fix async creation with signal from model before it's finished.
37 onRowsInserted: {
38 if (submenuIndex !== undefined && first <= submenuIndex) {
39 reset(true);
40 }
41 }
42 onRowsRemoved: {
43 if (submenuIndex !== undefined && first <= submenuIndex) {
44 reset(true);
45 }
46 }
47 onModelReset: {
48 if (root.submenuIndex !== undefined) {
49 reset(true);
50 }
51 }
52 }
53
54 Component.onCompleted: {
55 reset(true);
56 dynamicChanges.ready = true;
57 }
58
59 function reset(clearModel) {
60 if (clearModel) {
61 clear();
62 var model = root.submenuIndex == undefined ? menuModel : menuModel.submenu(root.submenuIndex)
63 if (model) {
64 push(pageComponent, { "menuModel": model });
65 }
66 } else if (root.currentPage) {
67 root.currentPage.reset();
68 }
69 }
70
71 Component {
72 id: pageComponent
73 Page {
74 id: page
75
76 property alias menuModel: listView.model
77 property alias title: backLabel.title
78 property bool isSubmenu: false
79
80 function reset() {
81 listView.positionViewAtBeginning();
82 }
83
84 property QtObject factory: root.factory.createObject(page, { menuModel: page.menuModel } )
85
86 header: PageHeader {
87 id: backLabel
88 visible: page.isSubmenu
89 leadingActionBar.actions: [
90 Action {
91 iconName: "back"
92 text: i18n.tr("Back")
93 onTriggered: {
94 root.pop();
95 }
96 }
97 ]
98 }
99
100 ListView {
101 id: listView
102 objectName: "listView"
103
104 anchors {
105 top: page.isSubmenu ? backLabel.bottom : parent.top
106 left: parent.left
107 right: parent.right
108 bottom: parent.bottom
109 bottomMargin: Qt.inputMethod.visible ? (Qt.inputMethod.keyboardRectangle.height - root.anchors.bottomMargin) : 0
110
111 Behavior on bottomMargin {
112 NumberAnimation {
113 duration: 175
114 easing.type: Easing.OutQuad
115 }
116 }
117 // TODO - does ever frame.
118 onBottomMarginChanged: {
119 listView.positionViewAtIndex(listView.currentIndex, ListView.End)
120 }
121 }
122
123 // Don't load all the delegates (only max of 3 pages worth -1/0/+1)
124 cacheBuffer: Math.max(height * 3, units.gu(70))
125
126 // Only allow flicking if the content doesn't fit on the page
127 interactive: contentHeight > height
128
129 property int selectedIndex: -1
130 property bool blockCurrentIndexChange: false
131 // for count = 0
132 onCountChanged: {
133 if (count == 0 && selectedIndex != -1) {
134 selectedIndex = -1;
135 }
136 }
137 // for highlight following
138 onSelectedIndexChanged: {
139 if (currentIndex != selectedIndex) {
140 var blocked = blockCurrentIndexChange;
141 blockCurrentIndexChange = true;
142
143 currentIndex = selectedIndex;
144
145 blockCurrentIndexChange = blocked;
146 }
147 }
148 // for item addition/removal
149 onCurrentIndexChanged: {
150 if (!blockCurrentIndexChange) {
151 if (selectedIndex != -1 && selectedIndex != currentIndex) {
152 selectedIndex = currentIndex;
153 }
154 }
155 }
156
157 Connections {
158 target: listView.model ? listView.model : null
159 onRowsAboutToBeRemoved: {
160 // track current item deletion.
161 if (listView.selectedIndex >= first && listView.selectedIndex <= last) {
162 listView.selectedIndex = -1;
163 }
164 }
165 }
166
167 delegate: Loader {
168 id: loader
169 objectName: "menuItem" + index
170 width: ListView.view.width
171 visible: status == Loader.Ready
172
173 property int modelIndex: index
174 sourceComponent: page.factory.load(model)
175
176 onLoaded: {
177 if (item.hasOwnProperty("selected")) {
178 item.selected = listView.selectedIndex == index;
179 }
180 if (item.hasOwnProperty("menuSelected")) {
181 item.menuSelected.connect(function() { listView.selectedIndex = index; });
182 }
183 if (item.hasOwnProperty("menuDeselected")) {
184 item.menuDeselected.connect(function() { listView.selectedIndex = -1; });
185 }
186 if (item.hasOwnProperty("menuData")) {
187 item.menuData = Qt.binding(function() { return model; });
188 }
189 if (item.hasOwnProperty("menuIndex")) {
190 item.menuIndex = Qt.binding(function() { return modelIndex; });
191 }
192 if (item.hasOwnProperty("clicked")) {
193 item.clicked.connect(function() {
194 if (model.hasSubmenu) {
195 page.menuModel.aboutToShow(modelIndex);
196 root.push(pageComponent, {
197 "isSubmenu": true,
198 "title": model.label.replace(/_|&/, ""),
199 "menuModel": page.menuModel.submenu(modelIndex)
200 });
201 }
202 });
203 }
204 }
205
206 Binding {
207 target: item ? item : null
208 property: "objectName"
209 value: model.action
210 }
211
212 // TODO: Fixes lp#1243146
213 // This is a workaround for a Qt bug. https://bugreports.qt-project.org/browse/QTBUG-34351
214 Connections {
215 target: listView
216 onSelectedIndexChanged: {
217 if (loader.item && loader.item.hasOwnProperty("selected")) {
218 loader.item.selected = listView.selectedIndex == index;
219 }
220 }
221 }
222 }
223 }
224 }
225 }
226}