Report of Forgerock work
authorJosé Bollo <jose.bollo@iot.bzh>
Tue, 28 Mar 2017 11:29:48 +0000 (13:29 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Wed, 26 Jul 2017 11:00:12 +0000 (13:00 +0200)
The work was originally made for the CES 2017.
Since this time, the repository changed and the
project evolved. This commit report the work
done to the new project.

Change-Id: Ia7365e03355792d6517e539c5710de7c269fb12f
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
59 files changed:
homescreen/homescreen.pro
homescreen/qml/Home.qml
homescreen/qml/MediaAreaBlank.qml
homescreen/qml/ShortcutArea.qml
homescreen/qml/ShortcutIcon.qml
homescreen/qml/StatusArea.qml
homescreen/qml/TopArea.qml
homescreen/qml/images/Home/B14-60.png [new file with mode: 0755]
homescreen/qml/images/Home/B14-90.png [new file with mode: 0755]
homescreen/qml/images/Home/DL_Alain.png [new file with mode: 0755]
homescreen/qml/images/Home/DL_Olivier.png [new file with mode: 0755]
homescreen/qml/images/Home/DL_Philippe.png [new file with mode: 0755]
homescreen/qml/images/Home/HMI_AppLauncher_Connectivity_Active-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Connectivity_Inactive-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Dashboard_Active-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Dashboard_Inactive-01.png
homescreen/qml/images/Home/HMI_AppLauncher_HVAC_Active-01.png
homescreen/qml/images/Home/HMI_AppLauncher_HVAC_Inactive-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Mixer_Active-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Mixer_Inactive-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Multimedia_Active-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Multimedia_Inactive-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Navigation_Active-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Navigation_Inactive-01.png
homescreen/qml/images/Home/HMI_AppLauncher_POI_Active-01.png
homescreen/qml/images/Home/HMI_AppLauncher_POI_Inactive-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Phone_Active-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Phone_Inactive-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Radio_Active-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Radio_Inactive-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Settings_Active-01.png
homescreen/qml/images/Home/HMI_AppLauncher_Settings_Inactive-01.png
homescreen/qml/images/Home/Install App.png [new file with mode: 0755]
homescreen/qml/images/Home/Logout-01.png [new file with mode: 0755]
homescreen/qml/images/Home/Open Trunk.png [new file with mode: 0755]
homescreen/qml/images/Home/Update Software.png [new file with mode: 0755]
homescreen/qml/images/Home/View Online.png [new file with mode: 0755]
homescreen/qml/images/Home/french_flag.png [new file with mode: 0755]
homescreen/qml/images/Home/home.qrc
homescreen/qml/images/Home/us_flag.png [new file with mode: 0755]
homescreen/qml/images/Home/visa.png [new file with mode: 0755]
homescreen/qml/images/Shortcut/HMI_Shortcut_HVAC-01.png
homescreen/qml/images/Shortcut/HMI_Shortcut_HVAC_Active-01.png
homescreen/qml/images/Shortcut/HMI_Shortcut_Home-01.png
homescreen/qml/images/Shortcut/HMI_Shortcut_Home_Active-01.png
homescreen/qml/images/Shortcut/HMI_Shortcut_Multimedia-01.png
homescreen/qml/images/Shortcut/HMI_Shortcut_Multimedia_Active-01.png
homescreen/qml/images/Shortcut/HMI_Shortcut_Navigation-01.png
homescreen/qml/images/Shortcut/HMI_Shortcut_Navigation_Active-01.png
homescreen/qml/images/Utility_Logo_Red-01.png [new file with mode: 0644]
homescreen/qml/images/images.qrc
homescreen/qml/main.qml
homescreen/src/appinfo.cpp
homescreen/src/appinfo.h
homescreen/src/applicationmodel.cpp
homescreen/src/applicationmodel.h
homescreen/src/main.cpp
homescreen/src/usermanagement.cpp [new file with mode: 0644]
homescreen/src/usermanagement.h [new file with mode: 0644]

index 1ca59b6..07b6b15 100644 (file)
@@ -14,7 +14,7 @@
 
 TEMPLATE = app
 TARGET = HomeScreen
-QT = qml quick dbus
+QT = qml quick widgets dbus websockets
 CONFIG += c++11
 
 include(../interfaces/interfaces.pri)
@@ -23,6 +23,7 @@ SOURCES += \
     src/main.cpp \
     src/homescreencontrolinterface.cpp \
     src/layouthandler.cpp \
+    src/usermanagement.cpp \
     src/applicationmodel.cpp \
     src/appinfo.cpp \
     src/statusbarmodel.cpp \
@@ -32,6 +33,7 @@ SOURCES += \
 HEADERS  += \
     src/homescreencontrolinterface.h \
     src/layouthandler.h \
+    src/usermanagement.h \
     src/statusbarmodel.h \
     src/statusbarserver.h \
     src/applicationlauncher.h \
index aa3a129..66d8b95 100644 (file)
  */
 
 import QtQuick 2.2
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 1.0
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
 import Home 1.0
 
 Item {
     id: root
+    property int pid: -1
+    signal languageChanged
+    signal disconnect
 
     Image {
         anchors.fill: parent
@@ -27,8 +34,176 @@ Item {
         anchors.bottomMargin: -215
         source: './images/AGL_HMI_Background_Car-01.png'
     }
+    Image {
+        id: sign90
+        width: 200
+        height: 200
+        anchors.horizontalCenter: parent.horizontalCenter
+        anchors.top: parent.top
+        anchors.topMargin: 20
+        source: './images/B14-90.png'
+        visible: false
+    }
+    Image {
+        id: flagLanguage
+        scale: 0.7
+        anchors.left: parent.left
+        anchors.leftMargin: 20
+        anchors.top: parent.top
+        anchors.topMargin: 10
+        source: './images/us_flag.png'
+        visible: true
+    }
+    Image {
+        id: visa
+        sourceSize.width: 170
+        anchors.right: parent.right
+        anchors.rightMargin: 20
+        anchors.top: parent.top
+        anchors.topMargin: 20
+        source: './images/visa.png'
+        visible: false
+        MouseArea {
+            anchors.fill: parent
+            onPressed: {
+                n1.target = visa
+                n1.start()
+            }
+            onReleased: {
+                n2.target = visa
+                n2.start()
+            }
+        }
+        Label {
+            id: cardNumber
+            anchors.top: parent.bottom
+            anchors.topMargin: 10
+            anchors.horizontalCenter: parent.horizontalCenter
+            horizontalAlignment:  Text.AlignHCenter
+            color: "white"
+            text: "111"
+            font.pixelSize: 20
+            font.family: "Roboto"
+        }
+    }
+    Image {
+        id: licence
+        sourceSize.width: 170
+        anchors.right: visa.right
+        anchors.top: visa.bottom
+        anchors.topMargin: 50
+        visible: false
+        MouseArea {
+            anchors.fill: parent
+            onPressed: {
+                n1.target = licence
+                n1.start()
+            }
+            onReleased: {
+                n2.target = licence
+                n2.start()
+            }
+        }
 
-    property int pid: -1
+    }
+    NumberAnimation {
+        id: n1
+        property: "sourceSize.width"
+        duration: 800
+        to: parent.width * .8
+        easing.type: Easing.InOutQuad
+        onStarted: target.z = 100
+    }
+    NumberAnimation {
+        id: n2
+        property: "sourceSize.width"
+        duration: 300
+        to: 170
+        easing.type: Easing.InOutQuad
+        onStopped: target.z = 0
+    }
+    Item {
+        id: hello
+        anchors.horizontalCenter: parent.horizontalCenter
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 40
+        visible: true
+        Text {
+            id: helloText
+            anchors.centerIn: parent
+            color: 'white'
+            text: 'No Authenticated User'
+            font.pixelSize: 40
+            font.family: 'Roboto'
+            SequentialAnimation on font.letterSpacing {
+                id: animation1
+                loops: 1;
+                NumberAnimation { from: 0; to: 50; easing.type: Easing.InQuad; duration: 3000 }
+                running: false
+                onRunningChanged: {
+                    if(running) {
+                        hello.visible = true
+                    } else {
+                        helloText.opacity = 1
+                        helloText.font.letterSpacing = 0
+                    }
+                }
+            }
+
+            SequentialAnimation on opacity {
+                id: animation2
+                loops: 1;
+                running: false
+                NumberAnimation { from: 1; to: 0; duration: 2600 }
+                PauseAnimation { duration: 400 }
+            }
+        }
+    }
+    function showHello(helloString) {
+        helloText.text = helloString
+        animation1.running = true;
+        animation2.running = true;
+    }
+
+    function showSign90(show, lang) {
+        sign90.visible = show
+        if(show) {
+            if(lang === 'fr')
+                sign90.source = './images/B14-90.png'
+            else
+                sign90.source = './images/B14-60.png'
+        }
+    }
+
+    function showVisa(show, num) {
+        visa.visible = show
+        cardNumber.text = num
+    }
+    function showLicence(show, licenceImage) {
+        if(show) {
+            licence.source = licenceImage
+            licence.visible = true
+        } else {
+            licence.visible = false
+        }
+    }
+
+    function changeFlag(flagImage) {
+        flagLanguage.source = flagImage
+    }
+    function setUser(type, auts) {
+        if(type === '') {
+            authorisations.visible = false
+        } else {
+            authorisations.visible = true
+            labelUserType.text = type
+            myModel.clear()
+            for (var i=0; i<auts.length; i++) {
+                if(auts[i] !== '')
+                    myModel.append({"name": auts[i]})
+            }
+        }
+    }
 
     GridView {
         anchors.centerIn: parent
@@ -43,8 +218,26 @@ Item {
             width: 320
             height: 320
             Image {
+                id: appImage
                 anchors.fill: parent
                 source: './images/HMI_AppLauncher_%1_%2-01.png'.arg(model.icon).arg(pressed ? 'Active' : 'Inactive')
+                Label {
+                    id: labelName
+                    anchors.horizontalCenter: parent.horizontalCenter
+                    horizontalAlignment: Text.AlignHCenter
+                    y: 257
+                    font.pixelSize: 32
+                    font.family: "Roboto"
+                    color: "white"
+                    text: '%1'.arg(model.name)
+                    function myChangeLanguage() {
+                        text = '%1'.arg(model.name)
+                        appImage.source = './images/HMI_AppLauncher_%1_%2-01.png'.arg(model.icon).arg(pressed ? 'Active' : 'Inactive')
+                    }
+                    Component.onCompleted: {
+                        root.languageChanged.connect(myChangeLanguage)
+                    }
+                }
             }
             onClicked: {
                 console.log("app is ", model.id)
@@ -54,7 +247,7 @@ Item {
 
                     applicationArea.visible = true
                     appLauncherAreaLauncher.visible = false
-                    layoutHandler.showAppLayer(pid)
+                    layoutHandler.showAppLayer(model.id, pid)
                 }
                 else {
                     console.warn("app cannot be launched!")
@@ -62,4 +255,81 @@ Item {
             }
         }
     }
+    ListModel {
+        id: myModel
+        ListElement {
+            name: 'Install App'
+        }
+        ListElement {
+            name: 'Open Trunk'
+        }
+        ListElement {
+            name: 'Update Software'
+        }
+        ListElement {
+            name: 'View Online'
+        }
+    }
+    Item {
+        id: authorisations
+        anchors.fill: parent
+        visible: false
+        GridLayout {
+            id: gridAut
+            columns: 2
+            anchors.bottom: parent.bottom
+            anchors.left: parent.left
+            anchors.bottomMargin: 50
+            anchors.leftMargin: 20
+            Repeater {
+                model: myModel
+                Image {
+                    source: './images/' + model.name + '.png'
+                    width: sourceSize.width
+                    height: sourceSize.height
+                    visible: true
+                }
+            }
+        }
+        Label {
+            id: labelUserType
+            anchors.bottom: gridAut.top
+            anchors.bottomMargin: 10
+            anchors.left: gridAut.left
+            color: "white"
+            text: "Owner"
+            font.pixelSize: 30
+            font.family: "Roboto"
+        }
+    }
+
+    Image {
+        id: logout
+        width: sourceSize.width
+        height: sourceSize.height
+        anchors.bottom: parent.bottom
+        anchors.right: parent.right
+        anchors.bottomMargin: 10
+        anchors.rightMargin: 20
+        source: './images/Logout-01.png'
+        visible: true
+        MouseArea {
+            anchors.fill: parent
+            onClicked: {
+                rotateLogout.start()
+                disconnect()
+                helloText.text= 'No Authenticated User'
+
+            }
+        }
+        RotationAnimator {
+            id: rotateLogout
+            target: logout;
+            from: 0;
+            to: 360;
+            loops: 1
+            duration: 500
+            running: false
+        }
+    }
 }
index 0dde451..37ee8e1 100644 (file)
@@ -23,7 +23,11 @@ Image {
     source: './images/Utility_Logo_Background-01.png'
 
     Image {
+        objectName: "Logo_colour"
         anchors.centerIn: parent
         source: './images/Utility_Logo_Colour-01.png'
+        function setImage(imagePath) {
+            source = imagePath
+        }
     }
 }
index 9be3fd0..835504c 100644 (file)
@@ -29,18 +29,53 @@ Item {
         ListElement {
             name: 'Home'
             application: ''
+            label: 'HOME'
         }
         ListElement {
             name: 'Multimedia'
             application: 'mediaplayer@0.1'
+            label: 'MULTIMEDIA'
         }
         ListElement {
             name: 'HVAC'
             application: 'hvac@0.1'
+            label: 'HVAC'
         }
         ListElement {
             name: 'Navigation'
             application: 'navigation@0.1'
+            label: 'NAVIGATION'
+        }
+    }
+    function languageChanged(lang) {
+        if(lang === "fr") {
+            applicationModel.setProperty(0, "label", 'ACCEUIL')
+
+            applicationModel.setProperty(2, "label", 'MULTIMÉDIA')
+            applicationModel.setProperty(2, "name", 'Multimedia')
+            applicationModel.setProperty(2, "application", 'mediaplayer@0.1')
+
+            applicationModel.setProperty(3, "label", 'CLIMATISATION')
+            applicationModel.setProperty(3, "name", 'HVAC')
+            applicationModel.setProperty(3, "application", 'hvac@0.1')
+
+            applicationModel.setProperty(1, "label", 'NAVIGATION')
+            applicationModel.setProperty(1, "name", 'Navigation')
+            applicationModel.setProperty(1, "application", 'navigation@0.1')
+        } else {
+            applicationModel.setProperty(0, "label", 'HOME')
+
+            applicationModel.setProperty(1, "label", 'MULTIMEDIA')
+            applicationModel.setProperty(1, "name", 'Multimedia')
+            applicationModel.setProperty(1, "application", 'mediaplayer@0.1')
+
+            applicationModel.setProperty(2, "label", 'HVAC')
+            applicationModel.setProperty(2, "name", 'HVAC')
+            applicationModel.setProperty(2, "application", 'hvac@0.1')
+
+            applicationModel.setProperty(3, "label", 'NAVIGATION')
+            applicationModel.setProperty(3, "name", 'Navigation')
+            applicationModel.setProperty(3, "application", 'navigation@0.1')
         }
     }
 
@@ -79,4 +114,10 @@ Item {
             }
         }
     }
+    Component.onCompleted: {
+        appLauncherAreaLauncher.visible = true
+        applicationArea.visible = false
+        layoutHandler.hideAppLayer()
+        launcher.current = ''
+    }
 }
index 6f8e05e..1891788 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 import QtQuick 2.2
+import QtQuick.Controls 1.0
 
 MouseArea {
     id: root
@@ -33,6 +34,16 @@ MouseArea {
         source: './images/Shortcut/HMI_Shortcut_%1_Active-01.png'.arg(root.name)
         opacity: 1.0 - icon.opacity
     }
+    Label {
+        id: labelName
+        anchors.horizontalCenter: parent.horizontalCenter
+        horizontalAlignment: Text.AlignHCenter
+        y: 155
+        font.pixelSize: 20
+        font.family: "Roboto"
+        color: "white"
+        text: '%1'.arg(model.label)
+    }
     states: [
         State {
             when: root.active
index 3fc3079..e58305f 100644 (file)
@@ -24,6 +24,62 @@ Item {
     id: root
     width: 295
     height: 218
+    function languageChanged(lang) {
+        if(lang === "fr") {
+            labelTime.text = Qt.formatTime(now, 'HH:mm').toUpperCase()
+            labelTemperature.text = '18°C'
+            switch(now.getDay()) {
+            case 1:
+                labelDay.text = 'LUNDI'
+                break
+            case 2:
+                labelDay.text = 'MARDI'
+                break
+            case 3:
+                labelDay.text = 'MERCREDI'
+                break
+            case 4:
+                labelDay.text = 'JEUDI'
+                break
+            case 5:
+                labelDay.text = 'VENDREDI'
+                break
+            case 6:
+                labelDay.text = 'SAMEDI'
+                break
+            case 7:
+                labelDay.text = 'DIMANCHE'
+                break
+            }
+
+        } else {
+            labelTime.text = Qt.formatTime(now, 'h:mm ap').toUpperCase()
+            labelTemperature.text = '64°F'
+            switch(now.getDay()) {
+            case 1:
+                labelDay.text = 'MONDAY'
+                break
+            case 2:
+                labelDay.text = 'TUESDAY'
+                break
+            case 3:
+                labelDay.text = 'WEDNESDAY'
+                break
+            case 4:
+                labelDay.text = 'THURSDAY'
+                break
+            case 5:
+                labelDay.text = 'FRIDAY'
+                break
+            case 6:
+                labelDay.text = 'SATURDAY'
+                break
+            case 7:
+                labelDay.text = 'SUNDAY'
+                break
+            }
+        }
+    }
 
     property date now: new Date
     Timer {
@@ -42,12 +98,14 @@ Item {
                 anchors.fill: parent
                 anchors.margins: 40
                 spacing: 0
-                Text {
+                Label {
+                    id: labelDay
                     Layout.fillWidth: true
                     Layout.fillHeight: true
                     text: Qt.formatDate(now, 'dddd').toUpperCase()
                     font.family: 'Roboto'
-                    font.pixelSize: 13
+//                    font.pixelSize: 13
+                    font.pixelSize: 18
                     color: 'white'
                     verticalAlignment:  Text.AlignVCenter
 //                    Rectangle {
@@ -59,7 +117,8 @@ Item {
 //                        z: -1
 //                    }
                 }
-                Text {
+                Label {
+                    id: labelTime
                     Layout.fillWidth: true
                     Layout.fillHeight: true
                     text: Qt.formatTime(now, 'h:mm ap').toUpperCase()
@@ -76,7 +135,8 @@ Item {
                     Image {
                         source: './images/Weather/WeatherIcons_Rain-01.png'
                     }
-                    Text {
+                    Label {
+                        id: labelTemperature
                         text: '64°F'
                         color: 'white'
                         font.family: 'Helvetica'
@@ -84,6 +144,7 @@ Item {
                     }
                 }
             }
+            Component.onCompleted: root.languageChanged("en")
         }
         ColumnLayout {
             id: icons
index 922742d..2d28e5e 100644 (file)
@@ -29,12 +29,14 @@ Image {
         spacing: 0
         ShortcutArea {
             id: shortcutArea
+            objectName: "ShortcutArea"
             Layout.fillWidth: true
             Layout.fillHeight: true
             Layout.preferredWidth: 785
         }
         StatusArea {
             id: statusArea
+            objectName: "StatusArea"
             Layout.fillWidth: true
             Layout.fillHeight: true
             Layout.preferredWidth: 295
diff --git a/homescreen/qml/images/Home/B14-60.png b/homescreen/qml/images/Home/B14-60.png
new file mode 100755 (executable)
index 0000000..012c314
Binary files /dev/null and b/homescreen/qml/images/Home/B14-60.png differ
diff --git a/homescreen/qml/images/Home/B14-90.png b/homescreen/qml/images/Home/B14-90.png
new file mode 100755 (executable)
index 0000000..155aea2
Binary files /dev/null and b/homescreen/qml/images/Home/B14-90.png differ
diff --git a/homescreen/qml/images/Home/DL_Alain.png b/homescreen/qml/images/Home/DL_Alain.png
new file mode 100755 (executable)
index 0000000..04f15d3
Binary files /dev/null and b/homescreen/qml/images/Home/DL_Alain.png differ
diff --git a/homescreen/qml/images/Home/DL_Olivier.png b/homescreen/qml/images/Home/DL_Olivier.png
new file mode 100755 (executable)
index 0000000..baf4f76
Binary files /dev/null and b/homescreen/qml/images/Home/DL_Olivier.png differ
diff --git a/homescreen/qml/images/Home/DL_Philippe.png b/homescreen/qml/images/Home/DL_Philippe.png
new file mode 100755 (executable)
index 0000000..151342a
Binary files /dev/null and b/homescreen/qml/images/Home/DL_Philippe.png differ
index 888d0bd..b37a2d9 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Connectivity_Active-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Connectivity_Active-01.png differ
index ab83b0e..c4b12a9 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Connectivity_Inactive-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Connectivity_Inactive-01.png differ
index 11d39e5..d1fba09 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Dashboard_Active-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Dashboard_Active-01.png differ
index 6c0b914..138ebf7 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Dashboard_Inactive-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Dashboard_Inactive-01.png differ
index efc11e9..deeb402 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_HVAC_Active-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_HVAC_Active-01.png differ
index b528376..92cd8a8 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_HVAC_Inactive-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_HVAC_Inactive-01.png differ
index 41c499d..303dbb1 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Mixer_Active-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Mixer_Active-01.png differ
index 93f81af..df5816c 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Mixer_Inactive-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Mixer_Inactive-01.png differ
index 1c99ac4..c1af827 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Multimedia_Active-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Multimedia_Active-01.png differ
index 0bed61d..9a9c96a 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Multimedia_Inactive-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Multimedia_Inactive-01.png differ
index e7ad085..e5bae8b 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Navigation_Active-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Navigation_Active-01.png differ
index dd40750..cc9cb1a 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Navigation_Inactive-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Navigation_Inactive-01.png differ
index 2df01d3..c52d5bb 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_POI_Active-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_POI_Active-01.png differ
index ec62b87..d55e5fb 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_POI_Inactive-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_POI_Inactive-01.png differ
index 2150581..7a079e2 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Phone_Active-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Phone_Active-01.png differ
index 61dcedc..0de908b 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Phone_Inactive-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Phone_Inactive-01.png differ
index 1aa5a01..8503ae2 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Radio_Active-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Radio_Active-01.png differ
index 616983e..f8693c9 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Radio_Inactive-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Radio_Inactive-01.png differ
index 1d13fd6..ff030ef 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Settings_Active-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Settings_Active-01.png differ
index 027f1fe..15bdeb8 100644 (file)
Binary files a/homescreen/qml/images/Home/HMI_AppLauncher_Settings_Inactive-01.png and b/homescreen/qml/images/Home/HMI_AppLauncher_Settings_Inactive-01.png differ
diff --git a/homescreen/qml/images/Home/Install App.png b/homescreen/qml/images/Home/Install App.png
new file mode 100755 (executable)
index 0000000..17da664
Binary files /dev/null and b/homescreen/qml/images/Home/Install App.png differ
diff --git a/homescreen/qml/images/Home/Logout-01.png b/homescreen/qml/images/Home/Logout-01.png
new file mode 100755 (executable)
index 0000000..5436ebc
Binary files /dev/null and b/homescreen/qml/images/Home/Logout-01.png differ
diff --git a/homescreen/qml/images/Home/Open Trunk.png b/homescreen/qml/images/Home/Open Trunk.png
new file mode 100755 (executable)
index 0000000..8fdb660
Binary files /dev/null and b/homescreen/qml/images/Home/Open Trunk.png differ
diff --git a/homescreen/qml/images/Home/Update Software.png b/homescreen/qml/images/Home/Update Software.png
new file mode 100755 (executable)
index 0000000..dd107fd
Binary files /dev/null and b/homescreen/qml/images/Home/Update Software.png differ
diff --git a/homescreen/qml/images/Home/View Online.png b/homescreen/qml/images/Home/View Online.png
new file mode 100755 (executable)
index 0000000..d1fa287
Binary files /dev/null and b/homescreen/qml/images/Home/View Online.png differ
diff --git a/homescreen/qml/images/Home/french_flag.png b/homescreen/qml/images/Home/french_flag.png
new file mode 100755 (executable)
index 0000000..948f828
Binary files /dev/null and b/homescreen/qml/images/Home/french_flag.png differ
index e73633e..8d4ad7b 100644 (file)
         <file>HMI_AppLauncher_Radio_Inactive-01.png</file>
         <file>HMI_AppLauncher_Settings_Active-01.png</file>
         <file>HMI_AppLauncher_Settings_Inactive-01.png</file>
+        <file>visa.png</file>
+        <file>french_flag.png</file>
+        <file>us_flag.png</file>
+        <file>Logout-01.png</file>
+        <file>Update Software.png</file>
+        <file>Open Trunk.png</file>
+        <file>Install App.png</file>
+        <file>View Online.png</file>
+        <file>B14-60.png</file>
+        <file>B14-90.png</file>
+        <file>DL_Alain.png</file>
+        <file>DL_Olivier.png</file>
+        <file>DL_Philippe.png</file>
     </qresource>
 </RCC>
diff --git a/homescreen/qml/images/Home/us_flag.png b/homescreen/qml/images/Home/us_flag.png
new file mode 100755 (executable)
index 0000000..a85592a
Binary files /dev/null and b/homescreen/qml/images/Home/us_flag.png differ
diff --git a/homescreen/qml/images/Home/visa.png b/homescreen/qml/images/Home/visa.png
new file mode 100755 (executable)
index 0000000..766f194
Binary files /dev/null and b/homescreen/qml/images/Home/visa.png differ
index f5188f5..221fe60 100644 (file)
Binary files a/homescreen/qml/images/Shortcut/HMI_Shortcut_HVAC-01.png and b/homescreen/qml/images/Shortcut/HMI_Shortcut_HVAC-01.png differ
index abe92d2..cbd625a 100644 (file)
Binary files a/homescreen/qml/images/Shortcut/HMI_Shortcut_HVAC_Active-01.png and b/homescreen/qml/images/Shortcut/HMI_Shortcut_HVAC_Active-01.png differ
index 9aca151..3685d4a 100644 (file)
Binary files a/homescreen/qml/images/Shortcut/HMI_Shortcut_Home-01.png and b/homescreen/qml/images/Shortcut/HMI_Shortcut_Home-01.png differ
index 696168f..4c64670 100644 (file)
Binary files a/homescreen/qml/images/Shortcut/HMI_Shortcut_Home_Active-01.png and b/homescreen/qml/images/Shortcut/HMI_Shortcut_Home_Active-01.png differ
index 229860c..797d893 100644 (file)
Binary files a/homescreen/qml/images/Shortcut/HMI_Shortcut_Multimedia-01.png and b/homescreen/qml/images/Shortcut/HMI_Shortcut_Multimedia-01.png differ
index b0a023c..3d831bf 100644 (file)
Binary files a/homescreen/qml/images/Shortcut/HMI_Shortcut_Multimedia_Active-01.png and b/homescreen/qml/images/Shortcut/HMI_Shortcut_Multimedia_Active-01.png differ
index 34b0671..a58534c 100644 (file)
Binary files a/homescreen/qml/images/Shortcut/HMI_Shortcut_Navigation-01.png and b/homescreen/qml/images/Shortcut/HMI_Shortcut_Navigation-01.png differ
index 98e6146..99fbc23 100644 (file)
Binary files a/homescreen/qml/images/Shortcut/HMI_Shortcut_Navigation_Active-01.png and b/homescreen/qml/images/Shortcut/HMI_Shortcut_Navigation_Active-01.png differ
diff --git a/homescreen/qml/images/Utility_Logo_Red-01.png b/homescreen/qml/images/Utility_Logo_Red-01.png
new file mode 100644 (file)
index 0000000..8c49068
Binary files /dev/null and b/homescreen/qml/images/Utility_Logo_Red-01.png differ
index 2d8e902..1323107 100644 (file)
@@ -6,5 +6,6 @@
         <file>Utility_Music_Background-01.png</file>
         <file>Utility_Radio_Background-01.png</file>
         <file>AGL_HMI_Background_NoCar-01.png</file>
+        <file>Utility_Logo_Red-01.png</file>
     </qresource>
 </RCC>
index 11bd9d5..f14c80a 100644 (file)
@@ -54,15 +54,16 @@ Window {
                 Layout.fillHeight: true
                 Layout.preferredHeight: 1920 - 218 - 215
 
-                visible: false
+                visible: true
             }
 
             Home {
                 id: appLauncherAreaLauncher
+                objectName: "Home"
                 Layout.fillWidth: true
                 Layout.fillHeight: true
                 Layout.preferredHeight: 1920 - 218 - 215
-                visible: true
+                visible: false
             }
 
             MediaArea {
index fd9a585..0c90ff4 100644 (file)
@@ -108,6 +108,10 @@ QString AppInfo::name() const
 {
     return d->name;
 }
+void AppInfo::setName(const QString &name)
+{
+    d->name = name;
+}
 
 QString AppInfo::description() const
 {
index 0d98b10..c5faf11 100644 (file)
@@ -56,6 +56,7 @@ public:
     friend QDBusArgument &operator <<(QDBusArgument &argument, const AppInfo &appInfo);
     friend const QDBusArgument &operator >>(const QDBusArgument &argument, AppInfo &appInfo);
 
+    void setName(const QString &name);
 private:
     class Private;
     QSharedDataPointer<Private> d;
index c43e1bc..6174b9b 100644 (file)
 #include "applicationmodel.h"
 #include "appinfo.h"
 
-#include <QtCore/QDebug>
-
 #include <QtDBus/QDBusInterface>
 #include <QtDBus/QDBusReply>
 
-#include "afm_user_daemon_proxy.h"
-
-extern org::AGL::afm::user *afm_user_daemon_proxy;
-
 class ApplicationModel::Private
 {
 public:
-    Private();
-
+    Private(ApplicationModel *parent);
+    QList<QList<int> > orders;
+    QList<AppInfo> originalData;
+private:
+    ApplicationModel *q;
+public:
+    QDBusInterface proxy;
     QList<AppInfo> data;
 };
 
-namespace {
-    QString get_icon_name(QJsonObject const &i)
-    {
-        QString icon = i["id"].toString().split("@").front();
-        if (icon == "hvac" || icon == "poi") {
-            icon = icon.toUpper();
-        } else if (icon == "mediaplayer") {
-            icon = "Multimedia";
-        } else {
-            icon[0] = icon[0].toUpper();
-        }
-        return icon;
+ApplicationModel::Private::Private(ApplicationModel *parent)
+    : q(parent)
+    , proxy(QStringLiteral("org.agl.homescreenappframeworkbinder"), QStringLiteral("/AppFramework"), QStringLiteral("org.agl.appframework"), QDBusConnection::sessionBus())
+{
+    QDBusReply<QList<AppInfo>> reply = proxy.call("getAvailableApps");
+    if (false)/*reply.isValid()) TODO: test for CES!  */ {
+        data = reply.value();
+    } else {
+        data.append(AppInfo(QStringLiteral("HVAC"), QStringLiteral("HVAC"), QStringLiteral("hvac@0.1")));
+        data.append(AppInfo(QStringLiteral("Navigation"), QStringLiteral("NAVIGATION"), QStringLiteral("navigation@0.1")));
+        data.append(AppInfo(QStringLiteral("Phone"), QStringLiteral("PHONE"), QStringLiteral("phone@0.1")));
+        data.append(AppInfo(QStringLiteral("Radio"), QStringLiteral("RADIO"), QStringLiteral("radio@0.1")));
+        data.append(AppInfo(QStringLiteral("Multimedia"), QStringLiteral("MULTIMEDIA"), QStringLiteral("mediaplayer@0.1")));
+        data.append(AppInfo(QStringLiteral("Mixer"), QStringLiteral("MIXER"), QStringLiteral("mixer@0.1")));
+        data.append(AppInfo(QStringLiteral("Dashboard"), QStringLiteral("DASHBOARD"), QStringLiteral("dashboard@0.1")));
+        data.append(AppInfo(QStringLiteral("Settings"), QStringLiteral("SETTINGS"), QStringLiteral("settings@0.1")));
+        data.append(AppInfo(QStringLiteral("POI"), QStringLiteral("POINT OF\nINTEREST"), QStringLiteral("poi@0.1")));
     }
+    originalData = data;
+    QList<int> o;
+    o << 5 << 4 << 3 << 7 << 8  << 0 << 2 << 1 << 6;
+    orders.append(o);
+    o.clear();
+    o << 0 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 ;
+    orders.append(o);
+    o.clear();
+    o << 3 << 8 << 1 << 0 << 2 << 7 << 5 << 4 << 6;
+    orders.append(o);
+    o.clear();
+    o << 2 << 7 << 3 << 8 << 4 << 0 << 1 << 5 << 6;
+    orders.append(o);
+    o.clear();
+    o << 2 << 7 << 3 << 8 << 4 << 0 << 1 << 5 << 6;
+    orders.append(o);
+    o.clear();
+    o << 6 << 0 << 2 << 1 << 7 << 3 << 5 << 4 << 8;
+    orders.append(o);
 }
-
-ApplicationModel::Private::Private()
+void ApplicationModel::changeOrder(const int &hash)
 {
-    QString apps = afm_user_daemon_proxy->runnables(QStringLiteral(""));
-    QJsonDocument japps = QJsonDocument::fromJson(apps.toUtf8());
-    for (auto const &app : japps.array()) {
-        QJsonObject const &jso = app.toObject();
-        auto const name = jso["name"].toString();
-        auto const id = jso["id"].toString();
-        auto const icon = get_icon_name(jso);
-        this->data.append(AppInfo(icon, name, id));
-        qDebug() << "name:" << name << "icon:" << icon << "id:" << id;
+    if(hash < 0) {
+        d->data = d->originalData;
+        return;
+    }
+    int order = qAbs(hash) % 7;
+    QList<int> o = d->orders.at(order);
+    QList<AppInfo> newData;
+    for(int i = 0; i < o.size(); ++i) {
+        newData.append(d->originalData.at(o.at(i)));
+    }
+    d->data = newData;
+}
+
+void ApplicationModel::changeLanguage(const QString &lang)
+{ //todo: use QT translator instead of hardcoded strings.
+    if(lang == "fr") {
+        d->originalData[0].setName("CLIMATISATION");
+        d->originalData[1].setName("NAVIGATION");
+        d->originalData[2].setName("TÉLÉPHONE");
+        d->originalData[3].setName("RADIO");
+        d->originalData[4].setName("MULTIMÉDIA");
+        d->originalData[5].setName("MIXER");
+        d->originalData[6].setName("TABLEAU DE\nBORD");
+        d->originalData[7].setName("PARAMÈTRES");
+        d->originalData[8].setName("POINT D'INTÉRÊT");
+    } else {
+        d->originalData[0].setName("HVAC");
+        d->originalData[1].setName("NAVIGATION");
+        d->originalData[2].setName("PHONE");
+        d->originalData[3].setName("RADIO");
+        d->originalData[4].setName("MULTIMEDIA");
+        d->originalData[5].setName("MIXER");
+        d->originalData[6].setName("DASHBOARD");
+        d->originalData[7].setName("SETTINGS");
+        d->originalData[8].setName("POINT OF\nINTEREST");
     }
 }
 
 ApplicationModel::ApplicationModel(QObject *parent)
     : QAbstractListModel(parent)
-    , d(new Private())
+    , d(new Private(this))
 {
+    setObjectName("ApplicationModel");
 }
 
 ApplicationModel::~ApplicationModel()
 {
-    delete this->d;
+    delete d;
 }
 
 int ApplicationModel::rowCount(const QModelIndex &parent) const
@@ -80,7 +129,7 @@ int ApplicationModel::rowCount(const QModelIndex &parent) const
     if (parent.isValid())
         return 0;
 
-    return this->d->data.count();
+    return d->data.count();
 }
 
 QVariant ApplicationModel::data(const QModelIndex &index, int role) const
@@ -91,13 +140,13 @@ QVariant ApplicationModel::data(const QModelIndex &index, int role) const
 
     switch (role) {
     case Qt::DecorationRole:
-        ret = this->d->data[index.row()].iconPath();
+        ret = d->data[index.row()].iconPath();
         break;
     case Qt::DisplayRole:
-        ret = this->d->data[index.row()].name();
+        ret = d->data[index.row()].name();
         break;
     case Qt::UserRole:
-        ret = this->d->data[index.row()].id();
+        ret = d->data[index.row()].id();
         break;
     default:
         break;
index bffc4c9..1dc4d72 100644 (file)
@@ -30,7 +30,8 @@ public:
 
     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
     QHash<int, QByteArray> roleNames() const override;
-
+    void changeLanguage(const QString &lang);
+    void changeOrder(const int &hash);
 private:
     class Private;
     Private *d;
index 28a8d38..641c38f 100644 (file)
@@ -26,6 +26,7 @@
 #include "applicationlauncher.h"
 #include "statusbarmodel.h"
 #include "applicationmodel.h"
+#include "usermanagement.h"
 #include "appinfo.h"
 #include "afm_user_daemon_proxy.h"
 
@@ -98,6 +99,7 @@ int main(int argc, char *argv[])
     engine.rootContext()->setContextProperty("layoutHandler", layoutHandler);
 
     engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
-
+    UserManagement userManagement(engine.rootObjects().first());
+    Q_UNUSED(userManagement);
     return a.exec();
 }
diff --git a/homescreen/src/usermanagement.cpp b/homescreen/src/usermanagement.cpp
new file mode 100644 (file)
index 0000000..2537afc
--- /dev/null
@@ -0,0 +1,354 @@
+#include "usermanagement.h"
+#include <QDebug>
+#include <QtCore/QJsonDocument>
+#include <QByteArray>
+UserManagement::UserManagement(QObject *root) : QObject()
+{
+    home = root->findChild<QObject *>("Home");
+    QObject::connect(home, SIGNAL(disconnect()),
+                         this, SLOT(slot_disconnect()));
+    logo = root->findChild<QObject *>("Logo_colour");
+    shortcutArea = root->findChild<QObject *>("ShortcutArea");
+    statusArea = root->findChild<QObject *>("StatusArea");
+    this->appModel = home->findChild<ApplicationModel *>("ApplicationModel");
+    sequence = 0;
+    isRed = false;
+    connect(&timerRed, SIGNAL(timeout()), this, SLOT(slot_turnOffRed()));
+    timerRed.setSingleShot(true);
+    timerRed.setInterval(3000);
+#ifdef REAL_SERVER
+    connectWebsockets();
+#else
+    pSocket = NULL;
+    connect(&timerTest, SIGNAL(timeout()), this, SLOT(slot_timerTest()));
+    timerTest.setSingleShot(false);
+    timerTest.start(5000);
+    launchServer();
+#endif
+}
+void UserManagement::slot_disconnect()
+{
+    appModel->changeLanguage("us");
+    appModel->changeOrder(-1);
+    timerRed.stop();
+    slot_turnOffRed();
+    QMetaObject::invokeMethod(home, "languageChanged");
+    QMetaObject::invokeMethod(shortcutArea, "languageChanged", Q_ARG(QVariant, "en"));
+    QMetaObject::invokeMethod(statusArea, "languageChanged", Q_ARG(QVariant, "en"));
+    QMetaObject::invokeMethod(home, "showSign90", Q_ARG(QVariant, false), Q_ARG(QVariant, "en"));
+    QMetaObject::invokeMethod(home, "showVisa", Q_ARG(QVariant, false), Q_ARG(QVariant, ""));
+    QMetaObject::invokeMethod(home, "showLicence", Q_ARG(QVariant, false), Q_ARG(QVariant, ""));
+    QMetaObject::invokeMethod(home, "changeFlag", Q_ARG(QVariant, "./images/us_flag.png"));
+    QMetaObject::invokeMethod(home, "setUser", Q_ARG(QVariant, ""), Q_ARG(QVariant, ""));
+    QVariantList list;
+    list << 2 << QString().setNum(++sequence) << "agl-identity-agent/logout" << true;
+    listToJson(list, &data);
+    slot_sendData();
+}
+
+void UserManagement::setUser(const User &user)
+{
+    int hash = qHash(user.name + user.first_name);
+    timerRed.stop();
+    appModel->changeLanguage(user.graphPreferredLanguage);
+    appModel->changeOrder(hash);
+    slot_turnOffRed();
+    QMetaObject::invokeMethod(home, "languageChanged");
+    QMetaObject::invokeMethod(shortcutArea, "languageChanged", Q_ARG(QVariant, user.graphPreferredLanguage));
+    QMetaObject::invokeMethod(statusArea, "languageChanged", Q_ARG(QVariant, user.graphPreferredLanguage));
+    QMetaObject::invokeMethod(home, "showSign90", Q_ARG(QVariant, !user.graphActions.contains("Exceed 90 Kph")), Q_ARG(QVariant, user.graphPreferredLanguage));
+    QStringList t;
+    foreach(const QString &s, user.graphActions) {
+        if(!s.contains("Exceed"))
+            t.append(s);
+    }
+    QString type = user.policy;
+    if(user.graphPreferredLanguage == "fr") {
+        if(type == "Owner")
+            type = "Propriétaire";
+        else if(type == "Driver")
+            type = "Conducteur";
+        else if(type == "Maintainer")
+            type = "Maintenance";
+    }
+    QMetaObject::invokeMethod(home, "setUser", Q_ARG(QVariant, type), Q_ARG(QVariant, QVariant::fromValue(t)));
+    if(user.ccNumberMasked.isEmpty())
+        QMetaObject::invokeMethod(home, "showVisa", Q_ARG(QVariant, false), Q_ARG(QVariant, ""));
+    else
+        QMetaObject::invokeMethod(home, "showVisa", Q_ARG(QVariant, true), Q_ARG(QVariant, user.ccNumberMasked));
+    const QString welcome = QString("%1").arg(user.graphPreferredLanguage == "fr" ? "Bonjour " : "Hello") + " ";
+    QMetaObject::invokeMethod(home, "showHello", Q_ARG(QVariant, welcome + user.first_name));
+    QMetaObject::invokeMethod(home, "changeFlag", Q_ARG(QVariant, user.graphPreferredLanguage == "fr" ? "./images/french_flag.png" : "./images/us_flag.png"));
+    if(user.name.toLower() == "philippea")
+        QMetaObject::invokeMethod(home, "showLicence", Q_ARG(QVariant, true), Q_ARG(QVariant, "./images/DL_Philippe.png"));
+    else if(user.name.toLower() == "alainp")
+        QMetaObject::invokeMethod(home, "showLicence", Q_ARG(QVariant, true), Q_ARG(QVariant, "./images/DL_Alain.png"));
+    else if(user.name.toLower() == "olivierc")
+        QMetaObject::invokeMethod(home, "showLicence", Q_ARG(QVariant, true), Q_ARG(QVariant, "./images/DL_Olivier.png"));
+    else
+        QMetaObject::invokeMethod(home, "showLicence", Q_ARG(QVariant, false), Q_ARG(QVariant, ""));
+
+}
+void UserManagement::slot_turnOffRed()
+{
+    if(!isRed)
+        return;
+    QMetaObject::invokeMethod(logo, "setImage", Q_ARG(QVariant, "./images/Utility_Logo_Colour-01.png"));
+    isRed = false;
+}
+
+void UserManagement::connectWebsockets()
+{
+#ifdef REAL_SERVER
+    const QUrl url(REAL_SERVER);
+#else
+    const QUrl url(QStringLiteral("ws://localhost:1234"));
+#endif
+    QSslConfiguration config = QSslConfiguration::defaultConfiguration();
+    config.setProtocol(QSsl::SecureProtocols);
+    webSocket.setSslConfiguration(config);
+    connect(&webSocket, &QWebSocket::connected, this, &UserManagement::onConnected);
+    connect(&webSocket, &QWebSocket::disconnected, this, &UserManagement::onClosed);
+    if(!connect(&webSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onWebSocketError(QAbstractSocket::SocketError)))) {
+        qWarning() << "Failed to connect to QWebSocket::error";
+    }
+    webSocket.open(QUrl(url));
+}
+void UserManagement::onWebSocketError(QAbstractSocket::SocketError)
+{
+    qWarning()<<"Websocket error:" << webSocket.errorString();
+}
+
+void UserManagement::onConnected()
+{
+    connect(&webSocket, &QWebSocket::textMessageReceived,
+            this, &UserManagement::onTextMessageReceived);
+    QVariantList list;
+    QByteArray json;
+    list << 2 << QString().setNum(++sequence) << "agl-identity-agent/subscribe" << true;
+    listToJson(list, &json);
+    webSocket.sendTextMessage(QString(json));
+    list .clear();
+    list << 2 << QString().setNum(++sequence) << "agl-identity-agent/scan" << true;
+    listToJson(list, &json);
+    webSocket.sendTextMessage(QString(json));
+}
+void UserManagement::onTextMessageReceived(QString message)
+{
+    QVariantList list;
+    const bool ok = jsonToList(message.toUtf8(), &list);
+    if(!ok || list.size() < 3) {
+        qWarning()<<"error 1 decoding json"<<list.size()<<message;
+        return;
+    }
+    QVariantMap map  = list.at(2).toMap();
+    if(list.first().toInt() == 5) {
+        if(!isRed)
+            QMetaObject::invokeMethod(logo, "setImage", Q_ARG(QVariant, "./images/Utility_Logo_Red-01.png"));
+        isRed = true;
+        timerRed.start();
+        map = map["data"].toMap();
+        if(map["eventName"].toString() == "login") {
+            //qWarning()<<"login received in client";
+            list.clear();
+            list << 2 << QString().setNum(++sequence) << "agl-identity-agent/get" << true;
+            listToJson(list, &data);
+            QTimer::singleShot(300, this, SLOT(slot_sendData()));
+        }
+        return;
+    }
+    if(list.first().toInt() == 3) {
+        if(!map.contains("response")) {
+            return;
+        }
+        map = map["response"].toMap();
+        User user;
+        user.postal_address = map["postal_address"].toString();
+        QStringList temp  = map["loc"].toString().split(",");
+        if(temp.size() == 2) {
+            user.loc.setX(temp.at(0).toDouble());
+            user.loc.setY(temp.at(1).toDouble());
+        }
+        user.graphActions = map["graphActions"].toString().split(",");
+        user.country = map["country"].toString();
+        user.mail = map["mail"].toString();
+        user.city = map["city"].toString();
+        user.graphEmail = map["graphEmail"].toString();
+        user.graphPreferredLanguage = map["graphPreferredLanguage"].toString();
+        user.ccNumberMasked = map["ccNumberMasked"].toString();
+        user.ccExpYear = map["ccExpYear"].toString();
+        user.ccExpMonth = map["ccExpMonth"].toString();
+        user.description = map["description"].toString();
+        user.groups = map["groups"].toStringList();
+        user.last_name = map["last_name"].toString();
+        user.ccNumber = map["ccNumber"].toString();
+        user.house_identifier = map["house_identifier"].toString();
+        user.phone = map["phone"].toString();
+        user.name = map["name"].toString();
+        user.state = map["state"].toString();
+        user.common_name = map["common_name"].toString();
+        user.fax = map["fax"].toString();
+        user.postal_code = map["postal_code"].toString();
+        user.first_name = map["first_name"].toString();
+        user.keytoken = map["keytoken"].toString();
+        user.policy = map["graphPolicies"].toString();
+        setUser(user);
+    }
+}
+void UserManagement::slot_sendData()
+{
+    webSocket.sendTextMessage(QString(data));
+}
+
+void UserManagement::onClosed()
+{
+    qWarning()<<"webSocket closed";
+}
+bool UserManagement::listToJson(const QList<QVariant> &list, QByteArray *json) const
+{
+    QVariant v(list);
+    *json = QJsonDocument::fromVariant(v).toJson(QJsonDocument::Compact);
+    return true;
+}
+bool UserManagement::jsonToList(const QByteArray &buf, QList<QVariant> *list) const
+{
+    if(!list)
+        return false;
+    QJsonParseError err;
+    QVariant v = QJsonDocument::fromJson(buf, &err).toVariant();
+    if(err.error != 0) {
+        qWarning() << "Error parsing json data" << err.errorString() << buf;
+        *list = QList<QVariant>();
+        return false;
+    }
+    *list = v.toList();
+    return true;
+}
+bool UserManagement::mapToJson( const QVariantMap &map, QByteArray *json) const
+{
+    if(!json)
+        return false;
+    QVariant v(map);
+    *json = QJsonDocument::fromVariant(v).toJson(QJsonDocument::Compact);
+    return true;
+}
+bool UserManagement::jsonToMap(const QByteArray &buf, QVariantMap *map) const
+{
+    if(!map)
+        return false;
+    QJsonParseError err;
+    QVariant v = QJsonDocument::fromJson(buf, &err).toVariant();
+    if(err.error != 0) {
+        qWarning() << "Error parsing json data" << err.errorString() << buf;
+        *map = QVariantMap();
+        return false;
+    }
+    *map = v.toMap();
+    return true;
+}
+#ifndef REAL_SERVER
+void UserManagement::launchServer()
+{
+      webSocketServer = new QWebSocketServer(QStringLiteral("My Server"),
+                                              QWebSocketServer::NonSecureMode, this);
+      if(webSocketServer->listen(QHostAddress::Any, 1234)) {
+          connect(webSocketServer, &QWebSocketServer::newConnection,
+                  this, &UserManagement::onServerNewConnection);
+          connect(webSocketServer, &QWebSocketServer::closed, this, &UserManagement::onServerClosed);
+          QTimer::singleShot(100, this, SLOT(connectWebsockets()));
+      } else {
+          qWarning()<<"unable to launch webSocket server";
+      }
+}
+void UserManagement::onServerNewConnection()
+{
+    pSocket = webSocketServer->nextPendingConnection();
+    connect(pSocket, &QWebSocket::textMessageReceived, this, &UserManagement::processTextMessage, Qt::UniqueConnection);
+    connect(pSocket, &QWebSocket::binaryMessageReceived, this, &UserManagement::processBinaryMessage, Qt::UniqueConnection);
+    connect(pSocket, &QWebSocket::disconnected, this, &UserManagement::serverSocketDisconnected, Qt::UniqueConnection);
+}
+void UserManagement::processTextMessage(QString message)
+{
+    QString clientDetails_1 = "{\"postal_address\":\"201 Mission Street\",\"loc\":\"37.7914374,-122.3950694\",\"graphActions\":\"Install App,Update Software,Open Trunk,View Online\""
+                              ",\"country\":\"USA\",\"mail\":\"bjensen@example.com\",\"city\":\"San Francisco\",\"graphEmail\":"
+                              "\"bjensen@example.com\",\"graphPreferredLanguage\":\"en\",\"ccNumberMasked\":\"-111\",\"ccExpYear\""
+                              ":\"19\",\"ccExpMonth\":\"01\",\"description\":\"Original description\",\"groups\":[],\"last_name\":\""
+                              "Jensen\",\"ccNumber\":\"111-2343-1121-111\",\"house_identifier\":\"ForgeRock\",\"phone\":\""
+                              "+1 408 555 1862\",\"name\":\"bjensen\",\"state\":\"CA\",\"common_name\":\"Barbara Jensen\",\"fax\":\""
+                              "+1 408 555 1862\",\"postal_code\":\"94105\",\"first_name\":\"Barbara\",\"keytoken\":\"a123456\",\"graphPolicies\":\"Driver\"}";
+    QString clientDetails_2 = "{\"postal_address\":\"201 Mission Street\",\"loc\":\"37.7914374,-122.3950694\""
+                              ",\"country\":\"USA\",\"mail\":\"bjensen@example.com\",\"city\":\"San Francisco\",\"graphEmail\":"
+                              "\"bjensen@example.com\",\"graphPreferredLanguage\":\"fr\",\"ccNumberMasked\":\"-222\",\"ccExpYear\""
+                              ":\"19\",\"ccExpMonth\":\"01\",\"description\":\"Original description\",\"groups\":[],\"last_name\":\""
+                              "Jensen\",\"ccNumber\":\"111-2343-1121-111\",\"house_identifier\":\"ForgeRock\",\"phone\":\""
+                              "+1 408 555 1862\",\"name\":\"bjensen\",\"state\":\"CA\",\"common_name\":\"Barbara Jensen\",\"fax\":\""
+                              "+1 408 555 1862\",\"postal_code\":\"94105\",\"first_name\":\"Philippe\",\"keytoken\":\"a123456\",\"graphPolicies\":\"Maintainer\"}";
+    QString clientDetails = clientDetails_1;
+    if(sequence % 2 == 1)
+        clientDetails = clientDetails_2;
+    QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
+    //qDebug() << "message received in server:" << message;
+    if (!pClient)
+        return;
+    QVariantList list;
+    if(!jsonToList(message.toUtf8(), &list))
+        return;
+    if(list.size() < 2)
+        return;
+    const int messType = list.at(0).toInt();
+    const QString messId = list.at(1).toString();
+    const QString cmd = list.at(2).toString();
+    list.clear();
+    QString reply;
+    switch(messType) {
+    case 2:
+        if(cmd == "agl-identity-agent/subscribe") {
+            reply = "[3,\"999maitai999\",{\"jtype\":\"afb-reply\",\"request\":{\"status\":\"success\",\"uuid\":\"1f2f7678-6f2e-4f54-b7b5-d0d4dcbf2e41\"}}]";
+        } else if (cmd == "agl-identity-agent/get") {
+            reply = "[3,\"999maitai99\",{\"jtype\":\"afb-reply\",\"request\":{\"status\":\"success\"},\"response\":....}]";
+            reply = reply.replace("....", clientDetails);
+        } else {
+            qWarning()<<"invalid cmd received:"<<cmd;
+            return;
+        }
+        break;
+    default:
+        qWarning()<<"invalid message type"<<messType;
+        return;
+        break;
+    }
+    reply = reply.replace("999maitai999", messId);
+    pClient->sendTextMessage(reply);
+}
+void UserManagement::processBinaryMessage(QByteArray message)
+{
+    QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
+    qDebug() << "Binary Message received ????:" << message;
+    if (pClient) {
+       // pClient->sendBinaryMessage(message);
+    }
+}
+void UserManagement::serverSocketDisconnected()
+{
+    QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
+    qDebug() << "socketDisconnected:" << pClient;
+    if (pClient) {
+        pClient->deleteLater();
+    }
+}
+void UserManagement::slot_timerTest()
+{
+    if(!pSocket)
+        return;
+    if(sequence > 3) {
+        timerTest.stop();
+        return;
+    }
+    pSocket->sendTextMessage("[5,\"agl-identity-agent/event\",{\"event\":\"agl-identity-agent\/event\",\"data\":{\"eventName\":\"incoming\",\"accountid\":\"D2:D4:71:0D:B5:F1\",\"nickname\":\"D2:D4:71:0D:B5:F1\"},\"jtype\":\"afb-event\"}]");
+    pSocket->sendTextMessage("[5,\"agl-identity-agent/event\",{\"event\":\"agl-identity-agent\/event\",\"data\":{\"eventName\":\"login\",\"accountid\":\"null\"},\"jtype\":\"afb-event\"}]");
+}
+void UserManagement::onServerClosed()
+{
+    qWarning()<<"websocket server closed";
+}
+#endif
diff --git a/homescreen/src/usermanagement.h b/homescreen/src/usermanagement.h
new file mode 100644 (file)
index 0000000..32db93f
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef USERMANAGEMENT_H
+#define USERMANAGEMENT_H
+
+#define REAL_SERVER "ws://localhost:1212/api?token=hello"
+
+#include <QObject>
+#include "applicationmodel.h"
+#include <QTimer>
+#include <QPointF>
+#include <QtWebSockets/QWebSocket>
+#ifndef REAL_SERVER
+#include <QtWebSockets/QWebSocketServer>
+#endif
+struct User {
+    QString postal_address;
+    QPointF loc;
+    QString country;
+    QString mail;
+    QString city;
+    QString graphEmail;
+    QString graphPreferredLanguage;
+    QString ccNumberMasked;
+    QString ccExpYear;
+    QString description;
+    QString ccExpMonth;
+    QStringList groups;
+    QString last_name;
+    QString ccNumber;
+    QString house_identifier;
+    QString phone;
+    QString name;
+    QString state;
+    QString fax;
+    QString common_name;
+    QString postal_code;
+    QString first_name;
+    QString keytoken;
+    QStringList graphActions;
+    QString policy;
+};
+
+class UserManagement : public QObject
+{
+    Q_OBJECT
+public:
+    explicit UserManagement(QObject *root);
+
+signals:
+
+public slots:
+    void connectWebsockets();
+    void onConnected();
+    void onClosed();
+    void onTextMessageReceived(QString message);
+    void onWebSocketError(QAbstractSocket::SocketError);
+    void slot_sendData();
+#ifndef REAL_SERVER
+    void onServerNewConnection();
+    void onServerClosed();
+    void processBinaryMessage(QByteArray message);
+    void processTextMessage(QString message);
+    void serverSocketDisconnected();
+    void slot_timerTest();
+#endif
+    void slot_turnOffRed();
+    void slot_disconnect();
+private:
+    QObject *home;
+    QObject *shortcutArea;
+    QObject *statusArea;
+    QObject *logo;
+    QByteArray data;
+    ApplicationModel *appModel;
+    QWebSocket webSocket;
+    QTimer timerRed;
+    bool isRed;
+    int sequence;
+    bool jsonToMap(const QByteArray &buf, QVariantMap *map) const;
+    bool mapToJson(const QVariantMap &map, QByteArray *json) const;
+    bool jsonToList(const QByteArray &buf, QList<QVariant> *list) const;
+    bool listToJson(const QList<QVariant> &list, QByteArray *json) const;
+    void setUser(const User &user);
+#ifndef REAL_SERVER
+    QTimer timerTest;
+    QWebSocket *pSocket;
+    QWebSocketServer *webSocketServer;
+    void launchServer();
+#endif
+};
+
+#endif // USERMANAGEMENT_H