Lomiri
Loading...
Searching...
No Matches
Page.qml
1/*
2 * Copyright (C) 2018 The UBports project
3 * Copyright (C) 2013-2016 Canonical Ltd.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18import QtQuick 2.12
19import Lomiri.Components 1.3
20import Wizard 0.1
21
22Item {
23 readonly property real maximumContentWidth: units.gu(50)
24 readonly property bool wideMode: width > units.gu(90) && width > height
25 readonly property alias contentAnimationRunning: contentAnimation.running
26
27 readonly property real buttonMargin: units.gu(3)
28 readonly property real buttonWidth: (width - buttonMargin * 2) / 2 -
29 buttonMargin / 2
30 readonly property real buttonBarHeight: units.gu(5)
31 readonly property real titleRectHeight: customTitle ? units.gu(10) : units.gu(16)
32
33 readonly property real topMargin: units.gu(11)
34 readonly property real bottomMargin: units.gu(3)
35 readonly property real leftMargin: Math.max(units.gu(3), (width - maximumContentWidth) / 3)
36 readonly property real rightMargin: leftMargin
37 readonly property real customMargin: wideMode ? units.gu(8) : units.gu(4) // margin for the content
38 readonly property real staticMargin: units.gu(3)
39
40 // colors
41 readonly property color backgroundColor: "#fdfdfd"
42 readonly property color dividerColor: LomiriColors.silk
43 readonly property color textColor: LomiriColors.slate
44 readonly property color errorColor: theme.palette.normal.negative
45 readonly property color okColor: theme.palette.normal.positive
46 readonly property color whiteColor: "white" // workaround for a UITK bug
47
48 // If you want to skip a page, mark skipValid false while you figure out
49 // whether to skip, then set it to true once you've determined the value
50 // of the skip property.
51 property bool skipValid: true
52 property bool skip: false
53
54 // Marks if should be only shown if update or install
55 property bool onlyOnUpdate: false
56 property bool onlyOnInstall: false
57
58 property bool hasBackButton: true
59 property string backButtonText: i18n.ctr("Button: Go back one page in the Wizard", "Back")
60 property bool customBack: false
61 property bool customTitle: false
62 property alias forwardButtonSourceComponent: forwardButton.sourceComponent
63 property alias content: contentHolder
64 property bool lastPage: false
65 property bool buttonBarVisible: true
66
67 // Item that will receive input focus when the page is in front
68 // May be useful to open the keyboard automatically for a text field
69 property Item focusItem
70
71 property string title: ""
72
73 signal backClicked()
74
75 visible: false
76 anchors.fill: parent
77
78 onVisibleChanged: {
79 if (visible && focusItem) {
80 focusItem.forceActiveFocus();
81 }
82 }
83
84 Timer {
85 id: indicatorTimer
86 interval: 1000
87 triggeredOnStart: true
88 repeat: true
89 running: System.wizardEnabled
90 onTriggered: {
91 indicatorTime.text = Qt.formatTime(new Date(), "h:mm")
92 }
93 }
94
95 // page header
96 Image {
97 id: titleRect
98 visible: !lastPage
99 anchors {
100 top: parent.top
101 left: parent.left
102 right: parent.right
103 }
104 source: customTitle ? "" : (wideMode ? "Pages/data/Desktop_header_bkg.png" : "Pages/data/Phone_header_bkg.png")
105 height: titleRectHeight
106 clip: true
107
108 // page title
109 Label {
110 id: titleLabel
111 property real animatedTopMargin: 0
112 anchors {
113 left: parent.left
114 right: parent.right
115 bottom: parent.bottom
116 bottomMargin: bottomMargin
117 leftMargin: staticMargin
118 rightMargin: rightMargin
119 topMargin: titleLabel.animatedTopMargin
120 }
121 text: title
122 color: customTitle ? textColor : backgroundColor
123 fontSize: customTitle ? "large" : "x-large"
124 font.weight: Font.Light
125 wrapMode: Text.WordWrap
126 maximumLineCount: 2
127 elide: Text.ElideRight
128 }
129
130 // indicators
131 Row {
132 id: indicatorRow
133 visible: !customTitle
134 anchors {
135 top: parent.top
136 right: parent.right
137 topMargin: units.gu(.5)
138 rightMargin: units.gu(.5)
139 }
140 height: units.gu(2)
141 spacing: units.gu(1)
142
143 Icon {
144 id: indicatorSim
145 anchors.verticalCenter: parent.verticalCenter
146 name: "no-simcard"
147 height: parent.height
148 width: height
149 visible: !(root.simManager0.present || root.simManager1.present) && root.modemManager.modems.length > 0
150 color: "white"
151 }
152
153 Icon {
154 id: indicatorNet
155 anchors.verticalCenter: parent.verticalCenter
156 name: Status.networkIcon
157 height: parent.height
158 width: height
159 color: "white"
160 }
161
162 Icon {
163 id: indicatorBattery
164 anchors.verticalCenter: parent.verticalCenter
165 name: Status.batteryIcon
166 height: parent.height
167 width: height * 1.4 // the battery icon is not rectangular :/
168 color: "white"
169 }
170
171 Label {
172 id: indicatorTime
173 anchors.verticalCenter: parent.verticalCenter
174 color: whiteColor
175 fontSize: "small"
176 }
177 }
178 }
179
180 // content
181 Item {
182 id: contentHolder
183 property real animatedMargin: 0
184 property real animatedTopMargin: 0
185 anchors {
186 top: titleRect.bottom
187 left: parent.left
188 right: parent.right
189 bottom: buttonBarVisible ? buttonRect.top : parent.bottom
190 leftMargin: content.animatedMargin
191 rightMargin: -content.animatedMargin
192 topMargin: content.animatedTopMargin
193 }
194 visible: opacity > 0
195 }
196
197 // button bar
198 Rectangle {
199 id: buttonRect
200 visible: buttonBarVisible
201 anchors {
202 bottom: parent.bottom
203 bottomMargin: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0
204 left: parent.left
205 right: parent.right
206 }
207 height: buttonBarHeight
208 color: "#f5f5f5"
209 z: content.z + 1
210
211 StackButton {
212 id: backButton
213 objectName: "backButton"
214 width: buttonWidth
215 anchors {
216 left: parent.left
217 bottom: parent.bottom
218 leftMargin: staticMargin
219 verticalCenter: parent.verticalCenter
220 }
221 text: backButtonText
222 visible: pageStack.depth > 1 && hasBackButton
223 backArrow: true
224
225 onClicked: customBack ? backClicked() : pageStack.prev()
226 }
227
228 Loader {
229 id: forwardButton
230 objectName: "forwardButton"
231 width: buttonWidth
232 anchors {
233 right: parent.right
234 bottom: parent.bottom
235 rightMargin: staticMargin
236 verticalCenter: parent.verticalCenter
237 }
238 }
239 }
240
241 // transitions
242 function aboutToShow(duration, direction) {
243 startContentAnimation(duration, direction)
244 startControlsAnimation(duration)
245 }
246
247 function aboutToShowSecondary(duration) {
248 secondaryAnimation.restart()
249 startControlsAnimation(duration)
250 }
251
252 function startContentAnimation(duration, direction) {
253 contentAnimation.animationDurationBase = duration
254 contentAnimation.direction = direction
255 contentAnimation.restart()
256 }
257
258 function startControlsAnimation(showDuration) {
259 actionsShowAnimation.showDuration = showDuration
260 actionsShowAnimation.restart()
261 }
262
263 SequentialAnimation { // animation for the button bar
264 id: actionsShowAnimation
265 property int showDuration: 0
266 PropertyAction {
267 target: buttonRect
268 property: 'opacity'
269 value: 0
270 }
271 PauseAnimation { duration: Math.max(0, actionsShowAnimation.showDuration - LomiriAnimation.SnapDuration) }
272 NumberAnimation {
273 target: buttonRect
274 property: 'opacity'
275 to: 1
276 duration: LomiriAnimation.SnapDuration
277 }
278 }
279
280 SequentialAnimation { // animations for the content
281 id: contentAnimation
282 objectName: "contentAnimation"
283 property int animationDurationBase: LomiriAnimation.BriskDuration
284 readonly property int additionalDuration: 200
285 property int direction: Qt.LeftToRight
286 ScriptAction { // direction of the effect
287 script: {
288 if (contentAnimation.direction === Qt.LeftToRight) {
289 content.animatedMargin = -content.width;
290 } else {
291 content.animatedMargin = content.width;
292 }
293 }
294 }
295 ParallelAnimation {
296 NumberAnimation { // the slide-in animation
297 targets: content
298 property: 'animatedMargin'
299 to: 0
300 duration: contentAnimation.animationDurationBase + contentAnimation.additionalDuration
301 easing.type: Easing.OutCubic
302 }
303 NumberAnimation { // opacity animation
304 targets: [titleLabel,content]
305 property: 'opacity'
306 from: 0
307 to: 1
308 duration: contentAnimation.animationDurationBase
309 }
310 }
311 }
312
313 ParallelAnimation { // animation for the secondary pages
314 id: secondaryAnimation
315 objectName: "secondaryAnimation"
316 NumberAnimation { // the slide-up animation
317 target: titleLabel
318 property: 'animatedTopMargin'
319 from: content.height
320 to: customMargin
321 duration: LomiriAnimation.BriskDuration
322 easing: LomiriAnimation.StandardEasing
323 }
324 NumberAnimation {
325 target: content
326 property: 'animatedTopMargin'
327 from: content.height
328 to: 0
329 duration: LomiriAnimation.BriskDuration
330 easing: LomiriAnimation.StandardEasing
331 }
332 NumberAnimation { // opacity animation
333 target: content
334 property: 'opacity'
335 from: 0
336 to: 1
337 duration: LomiriAnimation.BriskDuration
338 }
339 }
340}