~ken-vandine/address-book-app/add_profile

« back to all changes in this revision

Viewing changes to src/imports/Ubuntu/Contacts/FastScroll.qml

  • Committer: CI bot
  • Author(s): Tarmac, Renato Araujo Oliveira Filho
  • Date: 2014-06-16 13:12:46 UTC
  • mfrom: (169.1.22 release-2014-06-12)
  • Revision ID: ps-jenkins@lists.canonical.com-20140616131246-rzqpkq95ut0j8gka
Implemented contact share.
Replaced ContentHub API with QML API.
Removed ContactSearchListView component.
Moved ContactSimpleListView to the private API.
Added documentation for ContactListView properties.
Created "contactNameFilter" into ContactListView.
Update contact list visuals.
Implemented fast scroll.
Implemented contact search.
Initial refactor of autopilot tests.
Used new SDK header. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
 
4
** Copyright (C) 2014 Canonical Ltda
 
5
** All rights reserved.
 
6
** Contact: Nokia Corporation (qt-info@nokia.com)
 
7
**
 
8
** This file is part of the Qt Components project.
 
9
**
 
10
** $QT_BEGIN_LICENSE:BSD$
 
11
** You may use this file under the terms of the BSD license as follows:
 
12
**
 
13
** "Redistribution and use in source and binary forms, with or without
 
14
** modification, are permitted provided that the following conditions are
 
15
** met:
 
16
**   * Redistributions of source code must retain the above copyright
 
17
**     notice, this list of conditions and the following disclaimer.
 
18
**   * Redistributions in binary form must reproduce the above copyright
 
19
**     notice, this list of conditions and the following disclaimer in
 
20
**     the documentation and/or other materials provided with the
 
21
**     distribution.
 
22
**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
 
23
**     the names of its contributors may be used to endorse or promote
 
24
**     products derived from this software without specific prior written
 
25
**     permission.
 
26
**
 
27
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
28
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
29
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
30
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
31
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
32
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
33
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
34
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
35
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
36
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
37
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
// FastScroll.qml
 
43
import QtQuick 2.2
 
44
import Ubuntu.Components 1.1
 
45
import "FastScroll.js" as Sections
 
46
 
 
47
Item {
 
48
    id: root
 
49
 
 
50
    property ListView listView
 
51
    property int pinSize: units.gu(2)
 
52
 
 
53
    readonly property var letters: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"]
 
54
    readonly property alias fastScrolling: internal.fastScrolling
 
55
    readonly property bool showing: (rail.opacity !== 0.0)
 
56
 
 
57
    width: units.gu(7)
 
58
    onListViewChanged: {
 
59
        if (listView && listView.model) {
 
60
            internal.initDirtyObserver();
 
61
        } else if (listView) {
 
62
            listView.modelChanged.connect(function() {
 
63
                if (listView.model) {
 
64
                    internal.initDirtyObserver();
 
65
                }
 
66
            });
 
67
        }
 
68
    }
 
69
 
 
70
    Rectangle {
 
71
        id: magnified
 
72
 
 
73
        color: Theme.palette.normal.overlay
 
74
        radius: height * 0.3
 
75
        height: pinSize * 2
 
76
        width: height
 
77
        opacity: internal.fastScrolling ? 1.0 : 0.0
 
78
        x: -cursor.width - units.gu(3)
 
79
        y: {
 
80
            if (internal.currentItem) {
 
81
                var itemCenterY = rail.y + internal.currentItem.y + (internal.currentItem.height / 2)
 
82
                return (itemCenterY - (magnified.height / 2))
 
83
            } else {
 
84
                return 0
 
85
            }
 
86
        }
 
87
 
 
88
        Label {
 
89
            anchors.fill: parent
 
90
            horizontalAlignment: Text.AlignHCenter
 
91
            verticalAlignment: Text.AlignVCenter
 
92
            text: internal.desireSection
 
93
            fontSize: "small"
 
94
        }
 
95
 
 
96
        Behavior on opacity {
 
97
            UbuntuNumberAnimation {}
 
98
        }
 
99
    }
 
100
 
 
101
 
 
102
    Rectangle {
 
103
        id: cursor
 
104
 
 
105
        property bool showLabel: false
 
106
        property string currentSectionName: ""
 
107
 
 
108
        radius: pinSize * 0.3
 
109
        height: pinSize
 
110
        width: height
 
111
        color: Theme.palette.normal.foreground
 
112
        opacity: rail.opacity
 
113
        x: rail.x
 
114
        y: {
 
115
            if (internal.currentItem) {
 
116
                var itemCenterY = rail.y + internal.currentItem.y + (internal.currentItem.height / 2)
 
117
                return (itemCenterY - (cursor.height / 2))
 
118
            } else {
 
119
                return 0
 
120
            }
 
121
        }
 
122
        Behavior on y {
 
123
            enabled: !internal.fastScrolling
 
124
            UbuntuNumberAnimation { }
 
125
        }
 
126
    }
 
127
 
 
128
    Column {
 
129
        id: rail
 
130
 
 
131
        property bool isVisible: root.enabled && (listView.moving || dragArea.pressed)
 
132
 
 
133
        anchors {
 
134
            right: parent.right
 
135
            rightMargin: units.gu(2)
 
136
            left: parent.left
 
137
            leftMargin: units.gu(2)
 
138
            top: parent.top
 
139
        }
 
140
        height: childrenRect.height
 
141
        opacity: 0.0
 
142
        onIsVisibleChanged: {
 
143
            if (isVisible) {
 
144
                rail.opacity = 1.0
 
145
                hideTimer.stop()
 
146
            } else {
 
147
                hideTimer.restart()
 
148
            }
 
149
        }
 
150
 
 
151
        Behavior on opacity {
 
152
            UbuntuNumberAnimation { }
 
153
        }
 
154
 
 
155
        Repeater {
 
156
            id: sectionsRepeater
 
157
 
 
158
            model: root.letters
 
159
            Label {
 
160
                id: lbl
 
161
 
 
162
                anchors.left: parent.left
 
163
                height: pinSize
 
164
                width: pinSize
 
165
                verticalAlignment: Text.AlignVCenter
 
166
                horizontalAlignment: Text.AlignHCenter
 
167
                text: internal.fastScrolling && internal.targetSection == modelData ? "" : modelData
 
168
                fontSize: "x-small"
 
169
                color: internal.currentItem.text === text ? Theme.palette.selected.foregroundText : Theme.palette.selected.backgroundText
 
170
                opacity: !internal.modelDirty && Sections.contains(text) ? 1.0 : 0.5
 
171
            }
 
172
        }
 
173
 
 
174
        Timer {
 
175
            id: hideTimer
 
176
 
 
177
            running: false
 
178
            interval: 2000
 
179
            onTriggered: rail.opacity = 0.0
 
180
        }
 
181
    }
 
182
 
 
183
    MouseArea {
 
184
        id: dragArea
 
185
 
 
186
        anchors {
 
187
            left: parent.left
 
188
            right: parent.right
 
189
        }
 
190
        y: rail.y
 
191
        height: rail.height
 
192
        visible: rail.opacity == 1.0
 
193
 
 
194
        preventStealing: true
 
195
        onPressed: {
 
196
            internal.adjustContentPosition(mouseY)
 
197
            dragginTimer.start()
 
198
        }
 
199
 
 
200
        onReleased: {
 
201
            dragginTimer.stop()
 
202
            internal.desireSection = ""
 
203
            internal.fastScrolling = false
 
204
        }
 
205
 
 
206
        onPositionChanged: internal.adjustContentPosition(mouseY)
 
207
 
 
208
        Timer {
 
209
            id: dragginTimer
 
210
 
 
211
            running: false
 
212
            interval: 150
 
213
            onTriggered: {
 
214
                internal.fastScrolling = true
 
215
            }
 
216
        }
 
217
    }
 
218
 
 
219
    Timer {
 
220
        id: dirtyTimer
 
221
        interval: 500
 
222
        running: false
 
223
        onTriggered: {
 
224
            Sections.initSectionData(listView);
 
225
            internal.modelDirty = false;
 
226
        }
 
227
    }
 
228
 
 
229
    Timer {
 
230
        id: timerScroll
 
231
 
 
232
        running: false
 
233
        interval: 10
 
234
        onTriggered: {
 
235
            if (internal.desireSection != internal.currentSection) {
 
236
                var idx = Sections.getIndexFor(internal.desireSection)
 
237
                if (idx !== -1) {
 
238
                    listView.positionViewAtIndex(idx, ListView.Beginning)
 
239
                }
 
240
            }
 
241
        }
 
242
    }
 
243
 
 
244
    QtObject {
 
245
        id: internal
 
246
 
 
247
        property string currentSection: listView.currentSection
 
248
        property string desireSection: ""
 
249
        property string targetSection: fastScrolling ? desireSection : currentSection
 
250
        property int oldY: 0
 
251
        property bool modelDirty: false
 
252
        property bool down: true
 
253
        property bool fastScrolling: false
 
254
        property var currentItem: null
 
255
 
 
256
        onTargetSectionChanged: moveIndicator(targetSection)
 
257
 
 
258
        function initDirtyObserver() {
 
259
            Sections.initialize(listView);
 
260
            function dirtyObserver() {
 
261
                if (!internal.modelDirty) {
 
262
                    internal.modelDirty = true;
 
263
                    dirtyTimer.running = true;
 
264
                }
 
265
            }
 
266
 
 
267
            if (listView.model.countChanged)
 
268
                listView.model.countChanged.connect(dirtyObserver);
 
269
 
 
270
            if (listView.model.itemsChanged)
 
271
                listView.model.itemsChanged.connect(dirtyObserver);
 
272
 
 
273
            if (listView.model.itemsInserted)
 
274
                listView.model.itemsInserted.connect(dirtyObserver);
 
275
 
 
276
            if (listView.model.itemsMoved)
 
277
                listView.model.itemsMoved.connect(dirtyObserver);
 
278
 
 
279
            if (listView.model.itemsRemoved)
 
280
                listView.model.itemsRemoved.connect(dirtyObserver);
 
281
        }
 
282
 
 
283
        function adjustContentPosition(mouseY) {
 
284
            var child = rail.childAt(rail.width / 2, mouseY)
 
285
            if (!child || child.text === "") {
 
286
                return
 
287
            }
 
288
            var section = child.text
 
289
            if (internal.desireSection !== section) {
 
290
                internal.desireSection = section
 
291
                moveIndicator(section)
 
292
                timerScroll.restart()
 
293
            }
 
294
        }
 
295
 
 
296
        function moveIndicator(section)
 
297
        {
 
298
            var index = root.letters.indexOf(section)
 
299
            if (index != -1) {
 
300
                currentItem = sectionsRepeater.itemAt(index)
 
301
            }
 
302
        }
 
303
    }
 
304
}