Merge lp:~unity-team/unity/infographics-with-lightdm into lp:unity/phablet

Proposed by Nicolas d'Offay
Status: Superseded
Proposed branch: lp:~unity-team/unity/infographics-with-lightdm
Merge into: lp:unity/phablet
Prerequisite: lp:~mterry/unity/phablet-greeter-lightdm
Diff against target: 1686 lines (+1444/-35)
17 files modified
Greeter/Circle.qml (+59/-0)
Greeter/CirclePositioner.qml (+36/-0)
Greeter/Dot.qml (+36/-0)
Greeter/Greeter.qml (+1/-0)
Greeter/GreeterContent.qml (+18/-11)
Greeter/Infographics.qml (+293/-0)
plugins/LightDM/CMakeLists.txt (+4/-0)
plugins/LightDM/infographicmodel.cpp (+21/-0)
plugins/LightDM/infographicmodel.h (+26/-0)
plugins/LightDM/lightdm-infographicmodel.cpp (+539/-0)
plugins/LightDM/lightdm-infographicmodel.h (+91/-0)
plugins/LightDM/lightdm-usersmodel.cpp (+9/-21)
plugins/LightDM/lightdm-usersmodel.h (+1/-2)
plugins/LightDM/plugin.cpp (+11/-0)
plugins/LightDM/qvariantlistmodel.cpp (+243/-0)
plugins/LightDM/qvariantlistmodel.h (+55/-0)
tests/qmltests/CMakeLists.txt (+1/-1)
To merge this branch: bzr merge lp:~unity-team/unity/infographics-with-lightdm
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
MichaƂ Sawicz progress Pending
Michael Zanetti Pending
Review via email: mp+163308@code.launchpad.net

This proposal supersedes a proposal from 2013-05-10.

This proposal has been superseded by a proposal from 2013-05-14.

Commit message

Initial MP for review of QML only infographics.

Description of the change

This is an initial MP of the infographics with one animation. Currently everything is done via QML for the visuals however in future the circles will have to be rendered together via C++/GL. Any suggestions on what could be improved with the Infographics.qml would be much appreciated.

Tests will be introduced after the QML and any potential GL which needs to be done is completed.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:543
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~unity-team/unity/infographics-with-lightdm/+merge/163308/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/unity-phablet-ci/894/
Executed test runs:
    FAILURE: http://s-jenkins:8080/job/unity-phablet-qmluitests/827/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity-phablet-raring-armhf-ci/770/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity-phablet-raring-i386-ci/774/console

Click here to trigger a rebuild:
http://s-jenkins:8080/job/unity-phablet-ci/894/rebuild

review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'Greeter/Circle.qml'
2--- Greeter/Circle.qml 1970-01-01 00:00:00 +0000
3+++ Greeter/Circle.qml 2013-05-14 17:20:13 +0000
4@@ -0,0 +1,59 @@
5+/*
6+ * Copyright (C) 2013 Canonical, Ltd.
7+ *
8+ * This program is free software; you can redistribute it and/or modify
9+ * it under the terms of the GNU General Public License as published by
10+ * the Free Software Foundation; version 3.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ */
20+
21+import QtQuick 2.0
22+
23+Item {
24+ property color color
25+
26+ scale: 0.0
27+
28+ ShaderEffect {
29+ property real size: Math.min(width, height) * 0.5
30+ property variant scale: Qt.size(width >= height ? width / height : 1.0,
31+ width >= height ? 1.0 : height / width)
32+ property color color: Qt.rgba(parent.color.r * parent.color.a,
33+ parent.color.g * parent.color.a,
34+ parent.color.b * parent.color.a,
35+ parent.color.a)
36+
37+ visible: size > 0.0
38+ anchors.fill: parent
39+ vertexShader: "
40+ uniform mediump mat4 qt_Matrix;
41+ uniform mediump vec2 scale;
42+ attribute mediump vec4 qt_Vertex;
43+ attribute mediump vec2 qt_MultiTexCoord0;
44+ varying highp vec2 coord;
45+ void main() {
46+ // Put coord in the range [-1, 1].
47+ coord = ((qt_MultiTexCoord0 * 2.0) - 1.0) * scale;
48+ gl_Position = qt_Matrix * qt_Vertex;
49+ }
50+ "
51+ fragmentShader: "
52+ varying highp vec2 coord;
53+ uniform mediump float qt_Opacity;
54+ uniform mediump vec4 color;
55+ uniform mediump float size;
56+ void main() {
57+ // Distance function for antialiased circle.
58+ mediump float value = clamp(size + 0.5 - size * length(coord), 0.0, 1.0);
59+ gl_FragColor = color.rgba * vec4(qt_Opacity * value);
60+ }
61+ "
62+ }
63+}
64
65=== added file 'Greeter/CirclePositioner.qml'
66--- Greeter/CirclePositioner.qml 1970-01-01 00:00:00 +0000
67+++ Greeter/CirclePositioner.qml 2013-05-14 17:20:13 +0000
68@@ -0,0 +1,36 @@
69+/*
70+ * Copyright (C) 2013 Canonical, Ltd.
71+ *
72+ * This program is free software; you can redistribute it and/or modify
73+ * it under the terms of the GNU General Public License as published by
74+ * the Free Software Foundation; version 3.
75+ *
76+ * This program is distributed in the hope that it will be useful,
77+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
78+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
79+ * GNU General Public License for more details.
80+ *
81+ * You should have received a copy of the GNU General Public License
82+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
83+ */
84+
85+import QtQuick 2.0
86+import Ubuntu.Components 0.1
87+
88+Item {
89+ property int count
90+ property int index
91+ property real radius
92+ property real halfSize
93+ property real posOffset
94+
95+ property real slice: (2 * Math.PI / count) * index;
96+
97+ implicitWidth: childrenRect.width
98+ implicitHeight: childrenRect.height
99+
100+ x: (radius - halfSize * posOffset) * Math.sin(slice) + radius - halfSize
101+ y: (radius - halfSize * posOffset) * -Math.cos(slice) + radius - halfSize
102+
103+ rotation: Math.atan2(radius-(y+halfSize), radius-(x+halfSize)) * 180 / Math.PI - 90
104+}
105
106=== added file 'Greeter/Dot.qml'
107--- Greeter/Dot.qml 1970-01-01 00:00:00 +0000
108+++ Greeter/Dot.qml 2013-05-14 17:20:13 +0000
109@@ -0,0 +1,36 @@
110+/*
111+ * Copyright (C) 2013 Canonical, Ltd.
112+ *
113+ * This program is free software; you can redistribute it and/or modify
114+ * it under the terms of the GNU General Public License as published by
115+ * the Free Software Foundation; version 3.
116+ *
117+ * This program is distributed in the hope that it will be useful,
118+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
119+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
120+ * GNU General Public License for more details.
121+ *
122+ * You should have received a copy of the GNU General Public License
123+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
124+ */
125+
126+import QtQuick 2.0
127+
128+Image {
129+states: [
130+ State {
131+ name: "unfilled"
132+ PropertyChanges { target: dot; source: "graphics/dot_empty@30.png" }
133+ },
134+
135+ State {
136+ name: "filled"
137+ PropertyChanges { target: dot; source: "graphics/dot_filled@30.png" }
138+ },
139+
140+ State {
141+ name: "pointer"
142+ PropertyChanges { target: dot; source: "graphics/dot_pointer@30.png" }
143+ }
144+]
145+}
146
147=== modified file 'Greeter/Greeter.qml'
148--- Greeter/Greeter.qml 2013-05-02 19:24:24 +0000
149+++ Greeter/Greeter.qml 2013-05-14 17:20:13 +0000
150@@ -40,6 +40,7 @@
151 property variant model: LightDM.Users
152 property int currentIndex: 0
153 property bool promptless: item ? item.promptless : false
154+ property variant infographicModel: LightDM.Infographic
155
156 source: required ? "GreeterContent.qml" : ""
157
158
159=== modified file 'Greeter/GreeterContent.qml'
160--- Greeter/GreeterContent.qml 2013-05-07 14:18:30 +0000
161+++ Greeter/GreeterContent.qml 2013-05-14 17:20:13 +0000
162@@ -70,6 +70,8 @@
163
164 onLoaded: {
165 item.currentIndex = greeterContentLoader.currentIndex
166+ greeterContentLoader.infographicModel.username = greeterContentLoader.model.data(
167+ greeterContentLoader.currentIndex, LightDM.UserRoles.NameRole)
168 }
169
170 Binding {
171@@ -90,26 +92,31 @@
172 }
173
174 onCurrentIndexChanged: {
175- greeterContentLoader.currentIndex = loginLoader.item.currentIndex;
176+ if (greeterContentLoader.currentIndex !== loginLoader.item.currentIndex) {
177+ greeterContentLoader.currentIndex = loginLoader.item.currentIndex;
178+ greeterContentLoader.infographicModel.username = greeterContentLoader.model.data(
179+ greeterContentLoader.currentIndex, LightDM.UserRoles.NameRole)
180+ }
181 }
182 }
183 }
184
185- // FIXME: The images are way bigger than their content because the infographic
186- // bubbles can grow a lot. Because of that the infographic image reaches under the
187- // login list. This code makes sure that it never really overlaps until unusable
188- // with the current artwork. Will be replaced by real infographic.
189- CrossFadeImage {
190+ Infographics {
191 id: infographics
192- width: narrowMode ? sourceSize.width : Math.min(parent.width - loginLoader.x - loginLoader.width/2, units.gu(90))
193- height: narrowMode ? sourceSize.height : width * 8/9
194+ width: narrowMode ? parent.width : undefined
195+ height: narrowMode ? parent.height : 0.75 * parent.height
196+
197+ Component.onCompleted: {
198+ greeterContentLoader.infographicModel.username = "phablet"
199+ }
200+
201+ model: greeterContentLoader.infographicModel
202
203 anchors {
204 verticalCenter: parent.verticalCenter
205 horizontalCenter: narrowMode ? parent.horizontalCenter : undefined
206- right: narrowMode ? undefined : parent.right
207- rightMargin: narrowMode ? 0 : units.gu(-6)
208+ left: narrowMode ? undefined : loginLoader.right
209+ right: narrowMode ? undefined : root.right
210 }
211- source: narrowMode ? "graphics/infographic_tweeter_cut.png" : loginLoader.item.userList.model.data(currentIndex, LightDM.UserRoles.InfographicRole) ? loginLoader.item.userList.model.data(currentIndex, LightDM.UserRoles.InfographicRole) : ""
212 }
213 }
214
215=== added file 'Greeter/Infographics.qml'
216--- Greeter/Infographics.qml 1970-01-01 00:00:00 +0000
217+++ Greeter/Infographics.qml 2013-05-14 17:20:13 +0000
218@@ -0,0 +1,293 @@
219+/*
220+ * Copyright (C) 2013 Canonical, Ltd.
221+ *
222+ * This program is free software; you can redistribute it and/or modify
223+ * it under the terms of the GNU General Public License as published by
224+ * the Free Software Foundation; version 3.
225+ *
226+ * This program is distributed in the hope that it will be useful,
227+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
228+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
229+ * GNU General Public License for more details.
230+ *
231+ * You should have received a copy of the GNU General Public License
232+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
233+ */
234+
235+import QtQuick 2.0
236+import Ubuntu.Components 0.1
237+
238+Rectangle {
239+ id: infographic
240+
241+ property int animDuration: 10
242+
243+ Component.onCompleted: {
244+ dotAnimTimer.start()
245+ notification.showAnim.start()
246+ }
247+
248+ color: "transparent"
249+
250+ property variant model
251+
252+ Connections {
253+ target: model
254+
255+ onLabelChanged: {
256+ dotAnimTimer.dotCounter = circleAnimTimer.pastCircleCounter = circleAnimTimer.presentCircleCounter = 0
257+ dotAnimTimer.start()
258+ notification.showAnim.start()
259+ }
260+ }
261+
262+ visible: model.label !== ""
263+
264+ Item {
265+ id: dataCircle
266+
267+ width: Math.min(parent.height, parent.width) / 1.5
268+ height: width
269+
270+ anchors.centerIn: parent
271+
272+ Timer {
273+ id: circleAnimTimer
274+
275+ property int pastCircleCounter: 0
276+ property int presentCircleCounter: 0
277+
278+ interval: infographic.animDuration; running: false; repeat: true
279+ onTriggered: {
280+ if (pastCircleCounter < pastCircles.count) {
281+ var nextCircle = pastCircles.itemAt(pastCircleCounter++)
282+ if (nextCircle !== null) nextCircle.pastUnlockAnim.start()
283+ }
284+ if (pastCircleCounter >= pastCircles.count / 2) {
285+ var nextCircle = presentCircles.itemAt(presentCircleCounter++)
286+ if (nextCircle !== null) nextCircle.presentUnlockAnim.start()
287+ }
288+ if (presentCircleCounter >= presentCircles.count) {
289+ stop()
290+ pastCircleCounter = presentCircleCounter = 0
291+ }
292+ }
293+ }
294+
295+ Repeater {
296+ id: pastCircles
297+
298+ model: infographic.model.secondMonth
299+
300+ delegate: CirclePositioner {
301+ index: model.index
302+ count: pastCircles.count
303+ radius: parent.width / 2
304+ halfSize: pastCircle.width / 2
305+ posOffset: 0.0
306+ visible: modelData !== null
307+
308+ property variant pastUnlockAnim: pastCircleUnlockAnim
309+
310+ Circle {
311+ id: pastCircle
312+
313+ width: dataCircle.width / 2
314+ height: dataCircle.height / 2
315+
316+ Component.onCompleted: {
317+ color = infographic.model.secondColor
318+ }
319+
320+ SequentialAnimation {
321+ id: pastCircleUnlockAnim
322+
323+ loops: 1
324+ ParallelAnimation {
325+ PropertyAnimation {
326+ target: pastCircle
327+ property: "opacity"
328+ from: 0.0
329+ to: 0.1
330+ easing.type: Easing.OutCurve
331+ duration: circleAnimTimer.interval * 4
332+ }
333+ PropertyAnimation {
334+ target: pastCircle
335+ property: "scale"
336+ to: modelData
337+ easing.type: Easing.OutCurve
338+ duration: circleAnimTimer.interval * 4
339+ }
340+ }
341+ }
342+ }
343+ }
344+ }
345+
346+ Repeater {
347+ id: presentCircles
348+
349+ model: infographic.model.firstMonth
350+
351+ delegate: CirclePositioner {
352+ index: model.index
353+ count: presentCircles.count
354+ radius: parent.width / 2
355+ halfSize: presentCircle.width / 2
356+ posOffset: 0.0
357+ visible: modelData !== null
358+
359+ property variant presentUnlockAnim: presentCircleUnlockAnim
360+
361+ Circle {
362+ id: presentCircle
363+
364+ width: dataCircle.width / 2
365+ height: dataCircle.height / 2
366+
367+ Component.onCompleted: {
368+ color = infographic.model.firstColor
369+ }
370+
371+ SequentialAnimation {
372+ id: presentCircleUnlockAnim
373+
374+ loops: 1
375+
376+ ParallelAnimation {
377+ PropertyAnimation {
378+ target: presentCircle
379+ property: "opacity"
380+ from: 0.0
381+ to: 0.3
382+ easing.type: Easing.OutCurve
383+ duration: circleAnimTimer.interval * 4
384+ }
385+ PropertyAnimation {
386+ target: presentCircle
387+ property: "scale"
388+ from: 0.0
389+ to: modelData
390+ easing.type: Easing.OutCurve
391+ duration: circleAnimTimer.interval * 4
392+ }
393+ }
394+ }
395+ }
396+ }
397+ }
398+
399+ Image {
400+ id: backgroundCircle
401+
402+ anchors.fill: parent
403+ opacity: 0.9
404+
405+ source: "graphics/infographic_circle.png"
406+ }
407+
408+ Timer {
409+ id: dotAnimTimer
410+
411+ property int dotCounter: 0
412+
413+ interval: animDuration * 0.5; running: false; repeat: true
414+ onTriggered: {
415+ if (dotCounter < dots.count) {
416+ var nextDot = dots.itemAt(dotCounter++)
417+ nextDot.unlockAnimation.start()
418+ }
419+ else {
420+ stop()
421+ }
422+ if (dotCounter >= dots.count / 2) {
423+ circleAnimTimer.start()
424+ }
425+ }
426+ }
427+
428+ Repeater {
429+ id: dots
430+
431+ model: infographic.model.firstMonth
432+
433+ delegate: CirclePositioner {
434+ index: model.index
435+ count: dots.count
436+ radius: backgroundCircle.width / 2
437+ halfSize: dot.width / 2
438+ posOffset: radius / 180
439+ state: dot.state
440+
441+ property variant unlockAnimation: dotUnlockAnim
442+
443+ property int currentDay: infographic.model.currentDay
444+
445+ Dot {
446+ id: dot
447+
448+ visible: false
449+ smooth: true
450+ scale: radius / 1000
451+ state: {
452+ if (index < currentDay)
453+ "filled"
454+ else if (index == currentDay)
455+ "pointer"
456+ else
457+ "unfilled"
458+ }
459+
460+ SequentialAnimation {
461+ id: dotUnlockAnim
462+
463+ PropertyAnimation {
464+ target: dot
465+ property: "visible"
466+ to: "true"
467+ duration: dotAnimTimer.interval / 2
468+ }
469+ }
470+ }
471+ }
472+ }
473+
474+ Text {
475+ id: notification
476+
477+ height: 0.7 * backgroundCircle.width
478+ width: notification.height
479+ anchors.centerIn: parent
480+
481+ text: infographic.model.label
482+ font.pixelSize: notification.height / 10
483+
484+ wrapMode: Text.WordWrap
485+ horizontalAlignment: Text.AlignHCenter
486+ verticalAlignment: Text.AlignVCenter
487+ color: "white"
488+
489+ opacity: 0.0
490+
491+ property variant showAnim: increaseOpacity
492+
493+ PropertyAnimation {
494+ id: increaseOpacity
495+
496+ target: notification
497+ property: "opacity"
498+ to: 1.0
499+ duration: dotAnimTimer.interval * dots.count * 2
500+ }
501+ }
502+ }
503+
504+ MouseArea {
505+ anchors.fill: dataCircle
506+
507+ onClicked: {
508+ infographic.model.nextDataSource()
509+ }
510+ }
511+}
512
513=== added file 'Greeter/graphics/dot_empty@30.png'
514Binary files Greeter/graphics/dot_empty@30.png 1970-01-01 00:00:00 +0000 and Greeter/graphics/dot_empty@30.png 2013-05-14 17:20:13 +0000 differ
515=== added file 'Greeter/graphics/dot_filled@30.png'
516Binary files Greeter/graphics/dot_filled@30.png 1970-01-01 00:00:00 +0000 and Greeter/graphics/dot_filled@30.png 2013-05-14 17:20:13 +0000 differ
517=== added file 'Greeter/graphics/dot_pointer@30.png'
518Binary files Greeter/graphics/dot_pointer@30.png 1970-01-01 00:00:00 +0000 and Greeter/graphics/dot_pointer@30.png 2013-05-14 17:20:13 +0000 differ
519=== added file 'Greeter/graphics/infographic_circle.png'
520Binary files Greeter/graphics/infographic_circle.png 1970-01-01 00:00:00 +0000 and Greeter/graphics/infographic_circle.png 2013-05-14 17:20:13 +0000 differ
521=== removed file 'Greeter/graphics/infographic_default@20.png'
522Binary files Greeter/graphics/infographic_default@20.png 2013-02-12 17:43:28 +0000 and Greeter/graphics/infographic_default@20.png 1970-01-01 00:00:00 +0000 differ
523=== removed file 'Greeter/graphics/infographic_tweeter_cut@18.png'
524Binary files Greeter/graphics/infographic_tweeter_cut@18.png 2012-11-23 17:15:36 +0000 and Greeter/graphics/infographic_tweeter_cut@18.png 1970-01-01 00:00:00 +0000 differ
525=== modified file 'plugins/LightDM/CMakeLists.txt'
526--- plugins/LightDM/CMakeLists.txt 2013-05-09 14:05:05 +0000
527+++ plugins/LightDM/CMakeLists.txt 2013-05-14 17:20:13 +0000
528@@ -12,12 +12,15 @@
529 set(QMLPLUGIN_SRC
530 ../Utils/qsortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
531 greeter.cpp
532+ infographicmodel.cpp
533 plugin.cpp
534 usersmodel.cpp
535 # TODO: Once we split out a separate greeter process, we should move these
536 # files to a mock plugin and link this plugin to the real liblightdm
537 lightdm-greeter.cpp
538 lightdm-usersmodel.cpp
539+ lightdm-infographicmodel.cpp
540+ qvariantlistmodel.cpp
541 )
542
543 add_library(LightDM-qml MODULE
544@@ -43,3 +46,4 @@
545 install(FILES qmldir
546 DESTINATION ${SHELL_APP_DIR}/plugins/LightDM
547 )
548+
549
550=== added file 'plugins/LightDM/infographicmodel.cpp'
551--- plugins/LightDM/infographicmodel.cpp 1970-01-01 00:00:00 +0000
552+++ plugins/LightDM/infographicmodel.cpp 2013-05-14 17:20:13 +0000
553@@ -0,0 +1,21 @@
554+/*
555+ * Copyright (C) 2012,2013 Canonical, Ltd.
556+ *
557+ * This program is free software; you can redistribute it and/or modify
558+ * it under the terms of the GNU General Public License as published by
559+ * the Free Software Foundation; version 3.
560+ *
561+ * This program is distributed in the hope that it will be useful,
562+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
563+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
564+ * GNU General Public License for more details.
565+ *
566+ * You should have received a copy of the GNU General Public License
567+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
568+ *
569+ * Authors: Pete Woods <pete.woods@canonical.com>
570+ */
571+
572+#include "infographicmodel.h"
573+
574+#include "infographicmodel.moc"
575
576=== added file 'plugins/LightDM/infographicmodel.h'
577--- plugins/LightDM/infographicmodel.h 1970-01-01 00:00:00 +0000
578+++ plugins/LightDM/infographicmodel.h 2013-05-14 17:20:13 +0000
579@@ -0,0 +1,26 @@
580+/*
581+ * Copyright (C) 2012,2013 Canonical, Ltd.
582+ *
583+ * This program is free software; you can redistribute it and/or modify
584+ * it under the terms of the GNU General Public License as published by
585+ * the Free Software Foundation; version 3.
586+ *
587+ * This program is distributed in the hope that it will be useful,
588+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
589+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
590+ * GNU General Public License for more details.
591+ *
592+ * You should have received a copy of the GNU General Public License
593+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
594+ *
595+ * Authors: Pete Woods <pete.woods@canonical.com>
596+ */
597+
598+#ifndef INFOGRAPHICMODEL_H
599+#define INFOGRAPHICMODEL_H
600+
601+#include "lightdm-infographicmodel.h"
602+
603+typedef QLightDM::InfographicModel InfographicModel;
604+
605+#endif
606
607=== added file 'plugins/LightDM/lightdm-infographicmodel.cpp'
608--- plugins/LightDM/lightdm-infographicmodel.cpp 1970-01-01 00:00:00 +0000
609+++ plugins/LightDM/lightdm-infographicmodel.cpp 2013-05-14 17:20:13 +0000
610@@ -0,0 +1,539 @@
611+/*
612+ * Copyright (C) 2013 Canonical, Ltd.
613+ *
614+ * This program is free software; you can redistribute it and/or modify
615+ * it under the terms of the GNU General Public License as published by
616+ * the Free Software Foundation; version 3.
617+ *
618+ * This program is distributed in the hope that it will be useful,
619+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
620+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
621+ * GNU General Public License for more details.
622+ *
623+ * You should have received a copy of the GNU General Public License
624+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
625+ *
626+ * Author: Pete Woods <pete.woods@canonical.com>
627+ */
628+
629+// LightDM currently is Qt4 compatible, and so doesn't define setRoleNames.
630+// To use the same method of setting role name that it does, we
631+// set our compatibility to Qt4 here too.
632+#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(4, 0, 0)
633+
634+#include "lightdm-infographicmodel.h"
635+#include <QtCore/QDebug>
636+#include <QtCore/QDir>
637+#include <QtCore/QString>
638+#include <QtGui/QIcon>
639+
640+#include <QMultiMap>
641+
642+#include "qvariantlistmodel.h"
643+
644+#include <random>
645+
646+using namespace QLightDM;
647+
648+namespace QLightDM
649+{
650+
651+class InfographicData
652+{
653+public:
654+ explicit InfographicData(QObject *parent);
655+
656+ explicit InfographicData(const QString &label, const QColor &first_color,
657+ const QVariantList &first_month, const QColor &second_color,
658+ const QVariantList &second_month, QObject* parent);
659+
660+public:
661+ QObject * const q_ptr;
662+ QString label;
663+ QColor first_color;
664+ QVariantList first_month;
665+ QColor second_color;
666+ QVariantList second_month;
667+
668+private:
669+ Q_DECLARE_PUBLIC(QObject)
670+};
671+
672+class InfographicModelPrivate: QObject
673+{
674+Q_OBJECT
675+
676+public:
677+ explicit InfographicModelPrivate(InfographicModel *parent);
678+
679+ void generateFakeData();
680+
681+public Q_SLOTS:
682+ void nextFakeData();
683+
684+protected:
685+ InfographicModel * const q_ptr;
686+ QString label;
687+ QColor first_color;
688+ QVariantListModel first_month;
689+ QColor second_color;
690+ QVariantListModel second_month;
691+ int current_day;
692+ QString username;
693+ int data_index;
694+ QMultiMap<QString, QSharedPointer<InfographicData>> fake_data;
695+ QSharedPointer<InfographicData> empty_data;
696+
697+protected:
698+ void setFakeData(int data_index);
699+
700+private:
701+ Q_DECLARE_PUBLIC(InfographicModel)
702+};
703+}
704+
705+InfographicData::InfographicData(QObject *parent) :
706+ q_ptr(parent)
707+{
708+}
709+
710+InfographicData::InfographicData(const QString &label,
711+ const QColor &first_color, const QVariantList &first_month,
712+ const QColor &second_color, const QVariantList &second_month,
713+ QObject* parent) :
714+ q_ptr(parent), label(label), first_color(first_color), first_month(
715+ first_month), second_color(second_color), second_month(
716+ second_month)
717+{
718+}
719+
720+InfographicModelPrivate::InfographicModelPrivate(InfographicModel *parent) :
721+ q_ptr(parent), current_day(0)
722+{
723+ generateFakeData();
724+ setFakeData(0);
725+}
726+
727+void InfographicModelPrivate::generateFakeData()
728+{
729+ std::default_random_engine generator;
730+ std::normal_distribution<qreal> distribution(0.5, 0.2);
731+ auto rand = std::bind(distribution, generator);
732+
733+ QColor orange = QColor::fromRgbF(0.9, 0.3, 0.1, 1.0);
734+ QColor yellow = QColor::fromRgbF(1.0, 0.6, 0.0, 1.0);
735+ QColor red = QColor::fromRgbF(0.8, 0.0, 0.0, 1.0);
736+ QColor dark_purple = QColor::fromRgbF(0.5, 0.2, 0.3, 1.0);
737+ QColor light_purple = QColor::fromRgbF(0.8, 0.1, 0.8, 1.0);
738+ QColor pink(QColor::fromRgbF(0.75, 0.13, 0.75));
739+
740+ {
741+ empty_data.reset(new InfographicData(this));
742+ }
743+
744+ {
745+ QVariantList first_month;
746+ while (first_month.size() < 17)
747+ first_month.push_back(QVariant(rand()));
748+ while (first_month.size() < 31)
749+ first_month.push_back(QVariant());
750+ QVariantList second_month;
751+ while (second_month.size() < 31)
752+ second_month.push_back(QVariant(rand()));
753+ QSharedPointer<InfographicData> data(
754+ new InfographicData("Wow, you've walked <b>5</b>kms today",
755+ yellow, first_month, orange, second_month, this));
756+ fake_data.insert("phablet", data);
757+ }
758+
759+ {
760+ QVariantList first_month;
761+ while (first_month.size() < 17)
762+ first_month.push_back(QVariant(rand()));
763+ while (first_month.size() < 31)
764+ first_month.push_back(QVariant());
765+ QVariantList second_month;
766+ while (second_month.size() < 31)
767+ second_month.push_back(QVariant(rand()));
768+ QSharedPointer<InfographicData> data(
769+ new InfographicData("<b>2</b> places visited today", pink, first_month,
770+ orange, second_month, this));
771+ fake_data.insert("phablet", data);
772+ }
773+
774+ {
775+ QVariantList first_month;
776+ while (first_month.size() < 17)
777+ first_month.push_back(QVariant(rand()));
778+ while (first_month.size() < 31)
779+ first_month.push_back(QVariant());
780+ QVariantList second_month;
781+ while (second_month.size() < 31)
782+ second_month.push_back(QVariant(rand()));
783+ QSharedPointer<InfographicData> data(
784+ new InfographicData("You've received <b>15</b> messages today",
785+ orange, first_month, red, second_month, this));
786+ fake_data.insert("phablet", data);
787+ }
788+
789+ {
790+ QVariantList first_month( { 0.1, 0.2, 0.3, 0.4, 0.5, 0.7, 0.8, 0.9, 1.0,
791+ 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2 });
792+ while (first_month.size() < 31)
793+ first_month.push_back(QVariant());
794+ QVariantList second_month;
795+ while (second_month.size() < 31)
796+ second_month.push_back(QVariant(rand()));
797+ QSharedPointer<InfographicData> data(
798+ new InfographicData("Klout score of <b>50.20</b>", light_purple,
799+ first_month, dark_purple, second_month, this));
800+ fake_data.insert("phablet", data);
801+ }
802+
803+ {
804+ QVariantList first_month;
805+ while (first_month.size() < 17)
806+ first_month.push_back(QVariant(rand()));
807+ while (first_month.size() < 31)
808+ first_month.push_back(QVariant());
809+ QVariantList second_month;
810+ while (second_month.size() < 31)
811+ second_month.push_back(QVariant(rand()));
812+ QSharedPointer<InfographicData> data(
813+ new InfographicData("<b>1</b>hr watching videos today", red,
814+ first_month, dark_purple, second_month, this));
815+ fake_data.insert("phablet", data);
816+ }
817+
818+ {
819+ QVariantList first_month;
820+ while (first_month.size() < 20)
821+ first_month.push_back(QVariant(rand()));
822+ while (first_month.size() < 31)
823+ first_month.push_back(QVariant());
824+ QVariantList second_month;
825+ while (second_month.size() < 31)
826+ second_month.push_back(QVariant(rand()));
827+ QSharedPointer<InfographicData> data(
828+ new InfographicData("<b>4</b>hrs watching videos today", red,
829+ first_month, dark_purple, second_month, this));
830+ fake_data.insert("anna", data);
831+ }
832+
833+ {
834+ QVariantList first_month;
835+ while (first_month.size() < 20)
836+ first_month.push_back(QVariant(rand()));
837+ while (first_month.size() < 31)
838+ first_month.push_back(QVariant());
839+ QVariantList second_month;
840+ while (second_month.size() < 31)
841+ second_month.push_back(QVariant(rand()));
842+ QSharedPointer<InfographicData> data(
843+ new InfographicData("You've received <b>23</b> messages today",
844+ orange, first_month, red, second_month, this));
845+ fake_data.insert("anna", data);
846+ }
847+
848+ {
849+ QVariantList first_month;
850+ while (first_month.size() < 20)
851+ first_month.push_back(QVariant(rand()));
852+ while (first_month.size() < 31)
853+ first_month.push_back(QVariant());
854+ QVariantList second_month;
855+ while (second_month.size() < 31)
856+ second_month.push_back(QVariant(rand()));
857+ QSharedPointer<InfographicData> data(
858+ new InfographicData("<b>2</b> places visited today", pink, first_month,
859+ orange, second_month, this));
860+ fake_data.insert("anna", data);
861+ }
862+
863+ {
864+ QVariantList first_month;
865+ while (first_month.size() < 20)
866+ first_month.push_back(QVariant(rand()));
867+ while (first_month.size() < 31)
868+ first_month.push_back(QVariant(rand()));
869+ QVariantList second_month;
870+ while (second_month.size() < 31)
871+ second_month.push_back(QVariant());
872+ QSharedPointer<InfographicData> data(
873+ new InfographicData("<b>3</b> places visited today", pink, first_month,
874+ orange, second_month, this));
875+ fake_data.insert("toomas", data);
876+ }
877+
878+ {
879+ QVariantList first_month;
880+ while (first_month.size() < 20)
881+ first_month.push_back(QVariant(rand()));
882+ while (first_month.size() < 31)
883+ first_month.push_back(QVariant());
884+ QVariantList second_month;
885+ while (second_month.size() < 31)
886+ second_month.push_back(QVariant(rand()));
887+ QSharedPointer<InfographicData> data(
888+ new InfographicData("You've received <b>5</b> messages today",
889+ orange, first_month, red, second_month, this));
890+ fake_data.insert("toomas", data);
891+ }
892+
893+ {
894+ QVariantList first_month;
895+ while (first_month.size() < 17)
896+ first_month.push_back(QVariant(rand()));
897+ while (first_month.size() < 31)
898+ first_month.push_back(QVariant());
899+ QVariantList second_month;
900+ while (second_month.size() < 31)
901+ second_month.push_back(QVariant(rand()));
902+ QSharedPointer<InfographicData> data(
903+ new InfographicData("<b>8</b>hrs watching videos today", red,
904+ first_month, dark_purple, second_month, this));
905+ fake_data.insert("lois", data);
906+ }
907+
908+ {
909+ QVariantList first_month;
910+ while (first_month.size() < 17)
911+ first_month.push_back(QVariant(rand()));
912+ while (first_month.size() < 31)
913+ first_month.push_back(QVariant());
914+ QVariantList second_month;
915+ while (second_month.size() < 31)
916+ second_month.push_back(QVariant(rand()));
917+ QSharedPointer<InfographicData> data(
918+ new InfographicData("Klout score of <b>20.20</b>", light_purple,
919+ first_month, dark_purple, second_month, this));
920+ fake_data.insert("lois", data);
921+ }
922+
923+ {
924+ QVariantList first_month;
925+ while (first_month.size() < 17)
926+ first_month.push_back(QVariant(rand()));
927+ while (first_month.size() < 31)
928+ first_month.push_back(QVariant());
929+ QVariantList second_month;
930+ while (second_month.size() < 31)
931+ second_month.push_back(QVariant());
932+ QSharedPointer<InfographicData> data(
933+ new InfographicData("You've received <b>33</b> messages today",
934+ orange, first_month, red, second_month, this));
935+ fake_data.insert("lois", data);
936+ }
937+
938+ {
939+ QVariantList first_month;
940+ while (first_month.size() < 17)
941+ first_month.push_back(QVariant(rand()));
942+ while (first_month.size() < 31)
943+ first_month.push_back(QVariant());
944+ QVariantList second_month;
945+ while (second_month.size() < 31)
946+ second_month.push_back(QVariant(rand()));
947+ QSharedPointer<InfographicData> data(
948+ new InfographicData("<b>5</b> places visited today", pink, first_month,
949+ orange, second_month, this));
950+ fake_data.insert("lois", data);
951+ }
952+
953+ {
954+ QVariantList first_month;
955+ while (first_month.size() < 29)
956+ first_month.push_back(QVariant(rand()));
957+ while (first_month.size() < 31)
958+ first_month.push_back(QVariant());
959+ QVariantList second_month;
960+ while (second_month.size() < 31)
961+ second_month.push_back(QVariant(rand()));
962+ QSharedPointer<InfographicData> data(
963+ new InfographicData("<b>2</b>hrs watching videos today", red,
964+ first_month, dark_purple, second_month, this));
965+ fake_data.insert("toomas", data);
966+ }
967+
968+ {
969+ QVariantList first_month;
970+ while (first_month.size() < 29)
971+ first_month.push_back(QVariant(rand()));
972+ while (first_month.size() < 31)
973+ first_month.push_back(QVariant());
974+ QVariantList second_month;
975+ while (second_month.size() < 31)
976+ second_month.push_back(QVariant(rand()));
977+ QSharedPointer<InfographicData> data(
978+ new InfographicData("Wow, you've walked <b>5</b>kms today",
979+ yellow, first_month, orange, second_month, this));
980+ fake_data.insert("toomas", data);
981+ }
982+
983+ {
984+ QVariantList first_month;
985+ while (first_month.size() < 29)
986+ first_month.push_back(QVariant(rand()));
987+ while (first_month.size() < 31)
988+ first_month.push_back(QVariant(rand()));
989+ QVariantList second_month;
990+ while (second_month.size() < 31)
991+ second_month.push_back(QVariant());
992+ QSharedPointer<InfographicData> data(
993+ new InfographicData("<b>7</b> places visited today", pink, first_month,
994+ orange, second_month, this));
995+ fake_data.insert("toomas", data);
996+ }
997+
998+ {
999+ QVariantList first_month;
1000+ while (first_month.size() < 29)
1001+ first_month.push_back(QVariant(rand()));
1002+ while (first_month.size() < 31)
1003+ first_month.push_back(QVariant());
1004+ QVariantList second_month;
1005+ while (second_month.size() < 31)
1006+ second_month.push_back(QVariant(rand()));
1007+ QSharedPointer<InfographicData> data(
1008+ new InfographicData("You've received <b>55</b> messages today",
1009+ orange, first_month, red, second_month, this));
1010+ fake_data.insert("toomas", data);
1011+ }
1012+
1013+ {
1014+ QVariantList first_month;
1015+ while (first_month.size() < 29)
1016+ first_month.push_back(QVariant(rand()));
1017+ while (first_month.size() < 31)
1018+ first_month.push_back(QVariant());
1019+ QVariantList second_month;
1020+ while (second_month.size() < 31)
1021+ second_month.push_back(QVariant(rand()));
1022+ QSharedPointer<InfographicData> data(
1023+ new InfographicData("Klout score of <b>10.20</b>", light_purple,
1024+ first_month, dark_purple, second_month, this));
1025+ fake_data.insert("toomas", data);
1026+ }
1027+
1028+ {
1029+ QVariantList first_month;
1030+ while (first_month.size() < 15)
1031+ first_month.push_back(QVariant(rand()));
1032+ while (first_month.size() < 31)
1033+ first_month.push_back(QVariant());
1034+ QVariantList second_month;
1035+ while (second_month.size() < 31)
1036+ second_month.push_back(QVariant(rand()));
1037+ QSharedPointer<InfographicData> data(
1038+ new InfographicData("<b>6</b>hrs watching videos today", red,
1039+ first_month, dark_purple, second_month, this));
1040+ fake_data.insert("empty-name", data);
1041+ }
1042+}
1043+
1044+void InfographicModelPrivate::setFakeData(int new_index)
1045+{
1046+ qDebug() << "Data sets for user" << username << "= ["
1047+ << fake_data.values(username).size() << "], index = [" << new_index
1048+ << "]";
1049+
1050+ QSharedPointer<InfographicData> new_data;
1051+
1052+ if (!fake_data.contains(username))
1053+ {
1054+ data_index = 0;
1055+ new_data = empty_data;
1056+ } else
1057+ {
1058+ data_index = new_index;
1059+ new_data = fake_data.values(username).at(data_index);
1060+ }
1061+
1062+ label = new_data->label;
1063+ first_color = new_data->first_color;
1064+ first_month.setVariantList(new_data->first_month);
1065+ second_color = new_data->second_color;
1066+ second_month.setVariantList(new_data->second_month);
1067+
1068+ for (int i(first_month.rowCount()); i != 0; --i)
1069+ {
1070+ if (!first_month.data(first_month.index(i), Qt::DisplayRole).isNull())
1071+ {
1072+ current_day = i;
1073+ break;
1074+ }
1075+
1076+ }
1077+
1078+ q_ptr->labelChanged(label);
1079+ q_ptr->firstColorChanged(first_color);
1080+ q_ptr->secondColorChanged(second_color);
1081+ q_ptr->currentDayChanged(current_day);
1082+}
1083+
1084+void InfographicModelPrivate::nextFakeData()
1085+{
1086+ if (!fake_data.contains(username))
1087+ {
1088+ return;
1089+ }
1090+
1091+ setFakeData((data_index + 1) % fake_data.values(username).size());
1092+}
1093+
1094+InfographicModel::InfographicModel(QObject *parent) :
1095+ QObject(parent), d_ptr(new InfographicModelPrivate(this))
1096+{
1097+ connect(this, SIGNAL(nextDataSource()), d_ptr, SLOT(nextFakeData()));
1098+}
1099+
1100+InfographicModel::~InfographicModel()
1101+{
1102+ delete d_ptr;
1103+}
1104+
1105+QString InfographicModel::label() const
1106+{
1107+ return d_ptr->label;
1108+}
1109+
1110+QString InfographicModel::username() const
1111+{
1112+ return d_ptr->username;
1113+}
1114+
1115+void InfographicModel::setUsername(const QString &username)
1116+{
1117+ qDebug() << "Set username =" << username;
1118+ d_ptr->username = username;
1119+ d_ptr->setFakeData(0);
1120+ usernameChanged(d_ptr->username);
1121+}
1122+
1123+QColor InfographicModel::firstColor() const
1124+{
1125+ return d_ptr->first_color;
1126+}
1127+
1128+QColor InfographicModel::secondColor() const
1129+{
1130+ return d_ptr->second_color;
1131+}
1132+
1133+QAbstractItemModel * InfographicModel::firstMonth() const
1134+{
1135+ return &d_ptr->first_month;
1136+}
1137+
1138+QAbstractItemModel * InfographicModel::secondMonth() const
1139+{
1140+ return &d_ptr->second_month;
1141+}
1142+
1143+int InfographicModel::currentDay() const
1144+{
1145+ return d_ptr->current_day;
1146+}
1147+
1148+#include "lightdm-infographicmodel.moc"
1149+
1150
1151=== added file 'plugins/LightDM/lightdm-infographicmodel.h'
1152--- plugins/LightDM/lightdm-infographicmodel.h 1970-01-01 00:00:00 +0000
1153+++ plugins/LightDM/lightdm-infographicmodel.h 2013-05-14 17:20:13 +0000
1154@@ -0,0 +1,91 @@
1155+/*
1156+ * Copyright (C) 2013 Canonical, Ltd.
1157+ * Copyright (C) 2010-2011 David Edmundson.
1158+ *
1159+ * This program is free software; you can redistribute it and/or modify
1160+ * it under the terms of the GNU General Public License as published by
1161+ * the Free Software Foundation; version 3.
1162+ *
1163+ * This program is distributed in the hope that it will be useful,
1164+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1165+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1166+ * GNU General Public License for more details.
1167+ *
1168+ * You should have received a copy of the GNU General Public License
1169+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1170+ *
1171+ * Author: Pete Woods <pete.woods@canonical.com>
1172+ */
1173+
1174+#ifndef LIGHTDM_INFOGRAPHICMODEL_H
1175+#define LIGHTDM_INFOGRAPHICMODEL_H
1176+
1177+#include <QtCore/QString>
1178+#include <QtGui/qcolor.h>
1179+#include <QAbstractListModel>
1180+
1181+namespace QLightDM
1182+{
1183+class InfographicModelPrivate;
1184+
1185+class Q_DECL_EXPORT InfographicModel : public QObject
1186+{
1187+ Q_OBJECT
1188+
1189+ Q_PROPERTY(QString label READ label NOTIFY labelChanged FINAL)
1190+ Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged FINAL)
1191+ Q_PROPERTY(QColor firstColor READ firstColor NOTIFY firstColorChanged FINAL)
1192+ Q_PROPERTY(QColor secondColor READ secondColor NOTIFY secondColorChanged FINAL)
1193+ Q_PROPERTY(QAbstractItemModel *firstMonth READ firstMonth NOTIFY firstMonthChanged FINAL)
1194+ Q_PROPERTY(QAbstractItemModel *secondMonth READ secondMonth NOTIFY secondMonthChanged FINAL)
1195+ Q_PROPERTY(int currentDay READ currentDay NOTIFY currentDayChanged FINAL)
1196+
1197+public:
1198+ explicit InfographicModel(QObject *parent = 0);
1199+ ~InfographicModel();
1200+
1201+ QString label() const;
1202+
1203+ QString username() const;
1204+
1205+ void setUsername(const QString &username);
1206+
1207+ QColor firstColor() const;
1208+
1209+ QAbstractItemModel *firstMonth() const;
1210+
1211+ int currentDay() const;
1212+
1213+ QColor secondColor() const;
1214+
1215+ QAbstractItemModel *secondMonth() const;
1216+
1217+Q_SIGNALS:
1218+ void labelChanged(const QString &label);
1219+
1220+ void usernameChanged(const QString &username);
1221+
1222+ void firstColorChanged(const QColor &color);
1223+
1224+ void firstMonthChanged(QAbstractItemModel *first_month);
1225+
1226+ void currentDayChanged(int length);
1227+
1228+ void secondColorChanged(const QColor &color);
1229+
1230+ void secondMonthChanged(QAbstractItemModel *second_month);
1231+
1232+ void nextDataSource();
1233+
1234+protected:
1235+
1236+private:
1237+ InfographicModelPrivate * const d_ptr;
1238+
1239+ Q_DECLARE_PRIVATE(InfographicModel)
1240+
1241+};
1242+
1243+}
1244+
1245+#endif // LIGHTDM_INFOGRAPHICMODEL_H
1246
1247=== modified file 'plugins/LightDM/lightdm-usersmodel.cpp'
1248--- plugins/LightDM/lightdm-usersmodel.cpp 2013-05-02 17:42:30 +0000
1249+++ plugins/LightDM/lightdm-usersmodel.cpp 2013-05-14 17:20:13 +0000
1250@@ -39,18 +39,17 @@
1251 bool is_active;
1252 bool has_messages;
1253 QString session;
1254- QString infographic;
1255 };
1256
1257 const Entry fake_entries[] =
1258 {
1259- { "anna", "Anna Olson", "*", 0, false, false, 0, 0 },
1260- { "lois", "Lois Mcqueen", "*", 0, false, false, 0, 0 },
1261- { "lola", "Lola Chang", "*", 0, false, false, 0, 0 },
1262- { "toomas", "Toomas Vilms", "*", 0, false, false, 0, 0 },
1263- { "empty-name", "", "*", 0, false, false, 0, 0 },
1264- { "no-password", "Guest", "*", 0, false, false, 0, 0 },
1265- { "", "", 0, 0, false, false, 0, 0 }
1266+ { "anna", "Anna Olson", "*", 0, false, false, 0 },
1267+ { "lois", "Lois Mcqueen", "*", 0, false, false, 0 },
1268+ { "lola", "Lola Chang", "*", 0, false, false, 0 },
1269+ { "toomas", "Toomas Vilms", "*", 0, false, false, 0 },
1270+ { "empty-name", "", "*", 0, false, false, 0 },
1271+ { "no-password", "Guest", "*", 0, false, false, 0 },
1272+ { "", "", 0, 0, false, false, 0 }
1273 };
1274
1275 namespace QLightDM
1276@@ -77,12 +76,10 @@
1277
1278 void UsersModelPrivate::fillEntries()
1279 {
1280- QDir bgdir = QDir("/usr/share/backgrounds/");
1281+ QDir bgdir = QDir("/usr/share/demo-assets/shell/backgrounds/");
1282 QStringList backgrounds = bgdir.entryList(QDir::Files | QDir::NoDotAndDotDot);
1283- QDir infodir = QDir("/usr/share/demo-assets/shell/infographics/");
1284- QStringList infographics = infodir.entryList(QDir::Files | QDir::NoDotAndDotDot);
1285
1286- for (int i = 0, j = 0, k = 0; fake_entries[i].username != ""; i++) {
1287+ for (int i = 0, j = 0; fake_entries[i].username != ""; i++) {
1288 Entry entry = fake_entries[i];
1289 if (entry.background == "*") {
1290 if (backgrounds.isEmpty()) {
1291@@ -94,12 +91,6 @@
1292 }
1293 }
1294 }
1295- if (!infographics.isEmpty()) {
1296- entry.infographic = infodir.filePath(infographics[k++]);
1297- if (k >= infographics.length()) {
1298- k = 0;
1299- }
1300- }
1301 entries.append(entry);
1302 }
1303 }
1304@@ -119,7 +110,6 @@
1305 roles[SessionRole] = "session";
1306 roles[HasMessagesRole] = "hasMessages";
1307 roles[ImagePathRole] = "imagePath";
1308- roles[InfographicRole] = "infographic";
1309 setRoleNames(roles);
1310 d->fillEntries();
1311 }
1312@@ -170,8 +160,6 @@
1313 return d->entries[row].has_messages;
1314 case UsersModel::ImagePathRole:
1315 return "";
1316- case UsersModel::InfographicRole:
1317- return d->entries[row].infographic;
1318 default:
1319 return QVariant();
1320 }
1321
1322=== modified file 'plugins/LightDM/lightdm-usersmodel.h'
1323--- plugins/LightDM/lightdm-usersmodel.h 2013-04-20 20:55:20 +0000
1324+++ plugins/LightDM/lightdm-usersmodel.h 2013-05-14 17:20:13 +0000
1325@@ -46,8 +46,7 @@
1326 SessionRole,
1327 HasMessagesRole,
1328 ImagePathRole,
1329- BackgroundPathRole,
1330- InfographicRole // WARNING: not a real lightdm role
1331+ BackgroundPathRole
1332 };
1333
1334 int rowCount(const QModelIndex &parent) const;
1335
1336=== modified file 'plugins/LightDM/plugin.cpp'
1337--- plugins/LightDM/plugin.cpp 2013-05-09 14:05:05 +0000
1338+++ plugins/LightDM/plugin.cpp 2013-05-14 17:20:13 +0000
1339@@ -21,6 +21,8 @@
1340 #include "greeter.h"
1341 #include "lightdm-usersmodel.h"
1342 #include "usersmodel.h"
1343+#include "infographicmodel.h"
1344+
1345 #include <QtCore/QAbstractItemModel>
1346 #include <QtQml>
1347
1348@@ -38,10 +40,19 @@
1349 return new UsersModel();
1350 }
1351
1352+static QObject *infographic_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
1353+{
1354+ Q_UNUSED(engine)
1355+ Q_UNUSED(scriptEngine)
1356+ return new InfographicModel();
1357+}
1358+
1359 void LightDMPlugin::registerTypes(const char *uri)
1360 {
1361 Q_ASSERT(uri == QLatin1String("LightDM"));
1362 qmlRegisterSingletonType<Greeter>(uri, 0, 1, "Greeter", greeter_provider);
1363 qmlRegisterSingletonType<UsersModel>(uri, 0, 1, "Users", users_provider);
1364 qmlRegisterUncreatableType<QLightDM::UsersModel>(uri, 0, 1, "UserRoles", "Type is not instantiable");
1365+ qmlRegisterSingletonType<InfographicModel>(uri, 0, 1, "Infographic", infographic_provider);
1366 }
1367+
1368
1369=== added file 'plugins/LightDM/qvariantlistmodel.cpp'
1370--- plugins/LightDM/qvariantlistmodel.cpp 1970-01-01 00:00:00 +0000
1371+++ plugins/LightDM/qvariantlistmodel.cpp 2013-05-14 17:20:13 +0000
1372@@ -0,0 +1,243 @@
1373+/*
1374+ A simple model that uses a QVariantList as its data source.
1375+*/
1376+
1377+// LightDM currently is Qt4 compatible, and so doesn't define setRoleNames.
1378+// To use the same method of setting role name that it does, we
1379+// set our compatibility to Qt4 here too.
1380+#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(4, 0, 0)
1381+
1382+#include "qvariantlistmodel.h"
1383+
1384+#include <QtCore/qvector.h>
1385+
1386+
1387+/*!
1388+ \class QVariantListModel
1389+ \inmodule QtCore
1390+ \brief The QVariantListModel class provides a model that supplies variants to views.
1391+
1392+ \ingroup model-view
1393+
1394+ QVariantListModel is an editable model that can be used for simple
1395+ cases where you need to display a number of variants in a view
1396+ widget, such as a QListView or a QComboBox.
1397+
1398+ The model provides all the standard functions of an editable
1399+ model, representing the data in the variant list as a model with
1400+ one column and a number of rows equal to the number of items in
1401+ the list.
1402+
1403+ Model indexes corresponding to items are obtained with the
1404+ \l{QAbstractListModel::index()}{index()} function, and item flags
1405+ are obtained with flags(). Item data is read with the data()
1406+ function and written with setData(). The number of rows (and
1407+ number of items in the variant list) can be found with the
1408+ rowCount() function.
1409+
1410+ The model can be constructed with an existing variant list, or
1411+ variants can be set later with the setVariantList() convenience
1412+ function. Variants can also be inserted in the usual way with the
1413+ insertRows() function, and removed with removeRows(). The contents
1414+ of the variant list can be retrieved with the variantList()
1415+ convenience function.
1416+
1417+ An example usage of QVariantListModel:
1418+
1419+ \snippet qvariantlistmodel/main.cpp 0
1420+
1421+ \sa QAbstractListModel, QAbstractItemModel, {Model Classes}
1422+*/
1423+
1424+/*!
1425+ Constructs a variant list model with the given \a parent.
1426+*/
1427+
1428+QVariantListModel::QVariantListModel(QObject *parent)
1429+ : QAbstractListModel(parent)
1430+{
1431+ QHash<int, QByteArray> roles(roleNames());
1432+ roles[Qt::DisplayRole] = "modelData";
1433+ setRoleNames(roles);
1434+}
1435+
1436+/*!
1437+ Constructs a variant list model containing the specified \a list
1438+ with the given \a parent.
1439+*/
1440+
1441+QVariantListModel::QVariantListModel(const QVariantList &list, QObject *parent)
1442+ : QAbstractListModel(parent), lst(list)
1443+{
1444+ QHash<int, QByteArray> roles(roleNames());
1445+ roles[Qt::DisplayRole] = "modelData";
1446+ setRoleNames(roles);
1447+}
1448+
1449+/*!
1450+ Returns the number of rows in the model. This value corresponds to the
1451+ number of items in the model's internal variant list.
1452+
1453+ The optional \a parent argument is in most models used to specify
1454+ the parent of the rows to be counted. Because this is a list if a
1455+ valid parent is specified, the result will always be 0.
1456+
1457+ \sa insertRows(), removeRows(), QAbstractItemModel::rowCount()
1458+*/
1459+
1460+int QVariantListModel::rowCount(const QModelIndex &parent) const
1461+{
1462+ if (parent.isValid())
1463+ return 0;
1464+
1465+ return lst.count();
1466+}
1467+
1468+/*!
1469+ \reimp
1470+*/
1471+QModelIndex QVariantListModel::sibling(int row, int column, const QModelIndex &idx) const
1472+{
1473+ if (!idx.isValid() || column != 0 || row >= lst.count())
1474+ return QModelIndex();
1475+
1476+ return createIndex(row, 0);
1477+}
1478+
1479+/*!
1480+ Returns data for the specified \a role, from the item with the
1481+ given \a index.
1482+
1483+ If the view requests an invalid index, an invalid variant is returned.
1484+
1485+ \sa setData()
1486+*/
1487+
1488+QVariant QVariantListModel::data(const QModelIndex &index, int role) const
1489+{
1490+ if (index.row() < 0 || index.row() >= lst.size())
1491+ return QVariant();
1492+
1493+ if (role == Qt::DisplayRole || role == Qt::EditRole)
1494+ return lst.at(index.row());
1495+
1496+ return QVariant();
1497+}
1498+
1499+/*!
1500+ Returns the flags for the item with the given \a index.
1501+
1502+ Valid items are enabled, selectable, editable, drag enabled and drop enabled.
1503+
1504+ \sa QAbstractItemModel::flags()
1505+*/
1506+
1507+Qt::ItemFlags QVariantListModel::flags(const QModelIndex &index) const
1508+{
1509+ if (!index.isValid())
1510+ return QAbstractListModel::flags(index) | Qt::ItemIsDropEnabled;
1511+
1512+ return QAbstractListModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
1513+}
1514+
1515+/*!
1516+ Sets the data for the specified \a role in the item with the given
1517+ \a index in the model, to the provided \a value.
1518+
1519+ The dataChanged() signal is emitted if the item is changed.
1520+
1521+ \sa Qt::ItemDataRole, data()
1522+*/
1523+
1524+bool QVariantListModel::setData(const QModelIndex &index, const QVariant &value, int role)
1525+{
1526+ if (index.row() >= 0 && index.row() < lst.size()
1527+ && (role == Qt::EditRole || role == Qt::DisplayRole)) {
1528+ lst.replace(index.row(), value);
1529+ dataChanged(index, index, QVector<int>() << role);
1530+ return true;
1531+ }
1532+ return false;
1533+}
1534+
1535+/*!
1536+ Inserts \a count rows into the model, beginning at the given \a row.
1537+
1538+ The \a parent index of the rows is optional and is only used for
1539+ consistency with QAbstractItemModel. By default, a null index is
1540+ specified, indicating that the rows are inserted in the top level of
1541+ the model.
1542+
1543+ \sa QAbstractItemModel::insertRows()
1544+*/
1545+
1546+bool QVariantListModel::insertRows(int row, int count, const QModelIndex &parent)
1547+{
1548+ if (count < 1 || row < 0 || row > rowCount(parent))
1549+ return false;
1550+
1551+ beginInsertRows(QModelIndex(), row, row + count - 1);
1552+
1553+ for (int r = 0; r < count; ++r)
1554+ lst.insert(row, QVariant());
1555+
1556+ endInsertRows();
1557+
1558+ return true;
1559+}
1560+
1561+/*!
1562+ Removes \a count rows from the model, beginning at the given \a row.
1563+
1564+ The \a parent index of the rows is optional and is only used for
1565+ consistency with QAbstractItemModel. By default, a null index is
1566+ specified, indicating that the rows are removed in the top level of
1567+ the model.
1568+
1569+ \sa QAbstractItemModel::removeRows()
1570+*/
1571+
1572+bool QVariantListModel::removeRows(int row, int count, const QModelIndex &parent)
1573+{
1574+ if (count <= 0 || row < 0 || (row + count) > rowCount(parent))
1575+ return false;
1576+
1577+ beginRemoveRows(QModelIndex(), row, row + count - 1);
1578+
1579+ for (int r = 0; r < count; ++r)
1580+ lst.removeAt(row);
1581+
1582+ endRemoveRows();
1583+
1584+ return true;
1585+}
1586+
1587+/*!
1588+ Returns the variant list used by the model to store data.
1589+*/
1590+QVariantList QVariantListModel::variantList() const
1591+{
1592+ return lst;
1593+}
1594+
1595+/*!
1596+ Sets the model's internal variant list to \a list. The model will
1597+ notify any attached views that its underlying data has changed.
1598+
1599+ \sa dataChanged()
1600+*/
1601+void QVariantListModel::setVariantList(const QVariantList &list)
1602+{
1603+ beginResetModel();
1604+ lst = list;
1605+ endResetModel();
1606+}
1607+
1608+/*!
1609+ \reimp
1610+*/
1611+Qt::DropActions QVariantListModel::supportedDropActions() const
1612+{
1613+ return QAbstractItemModel::supportedDropActions() | Qt::MoveAction;
1614+}
1615+
1616
1617=== added file 'plugins/LightDM/qvariantlistmodel.h'
1618--- plugins/LightDM/qvariantlistmodel.h 1970-01-01 00:00:00 +0000
1619+++ plugins/LightDM/qvariantlistmodel.h 2013-05-14 17:20:13 +0000
1620@@ -0,0 +1,55 @@
1621+/*
1622+ * Copyright (C) 2013 Canonical, Ltd.
1623+ * Copyright (C) 2010-2011 David Edmundson.
1624+ *
1625+ * This program is free software; you can redistribute it and/or modify
1626+ * it under the terms of the GNU General Public License as published by
1627+ * the Free Software Foundation; version 3.
1628+ *
1629+ * This program is distributed in the hope that it will be useful,
1630+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1631+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1632+ * GNU General Public License for more details.
1633+ *
1634+ * You should have received a copy of the GNU General Public License
1635+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1636+ *
1637+ * Author: Pete Woods <pete.woods@canonical.com>
1638+ */
1639+
1640+#ifndef QVARIANTLISTMODEL_H
1641+#define QVARIANTLISTMODEL_H
1642+
1643+#include <QAbstractListModel>
1644+#include <QVariantList>
1645+
1646+class Q_CORE_EXPORT QVariantListModel : public QAbstractListModel
1647+{
1648+ Q_OBJECT
1649+public:
1650+ explicit QVariantListModel(QObject *parent = 0);
1651+ explicit QVariantListModel(const QVariantList &list, QObject *parent = 0);
1652+
1653+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
1654+ QModelIndex sibling(int row, int column, const QModelIndex &idx) const;
1655+
1656+ QVariant data(const QModelIndex &index, int role) const;
1657+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
1658+
1659+ Qt::ItemFlags flags(const QModelIndex &index) const;
1660+
1661+ bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
1662+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
1663+
1664+ QVariantList variantList() const;
1665+ void setVariantList(const QVariantList &list);
1666+
1667+ Qt::DropActions supportedDropActions() const;
1668+
1669+private:
1670+ Q_DISABLE_COPY(QVariantListModel)
1671+ QVariantList lst;
1672+};
1673+
1674+
1675+#endif // QVARIANTLISTMODEL_H
1676
1677=== modified file 'tests/qmltests/CMakeLists.txt'
1678--- tests/qmltests/CMakeLists.txt 2013-05-14 13:42:33 +0000
1679+++ tests/qmltests/CMakeLists.txt 2013-05-14 17:20:13 +0000
1680@@ -55,4 +55,4 @@
1681 add_qml_test(Panel Panel)
1682 add_qml_test(Panel SearchIndicator)
1683 add_qml_test(Panel/Menus IndicatorMenuWindow IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS})
1684-add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
1685+add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
1686\ No newline at end of file

Subscribers

People subscribed via source and target branches

to all changes: