summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorwang_zhiqiang <wang_zhiqiang@dl.cn.nexty-ele.com>2019-02-13 18:10:20 +0800
committerwang_zhiqiang <wang_zhiqiang@dl.cn.nexty-ele.com>2019-02-15 10:56:06 +0800
commitaee1b69e8e207081a3d8b2670980671a9fbc78b8 (patch)
tree86e71a4d08908c8c6711400a810bbbb00f19f803 /app
parent483c21f9d648f2cd58e00f39fcbee7b5dcbe2bc5 (diff)
Add onscreenapp
Onscreenapp is a qt application for showing onscreens. Applications can show/hide onscreen by calling homescreen-service's showWindow/hideWindow verb. Applications also can customize onscreen's title,type, display contents and buttons. Some images about onscreen pattern had uploaded in JIRA SPEC-1967. Bug-AGL: SPEC-1967 Change-Id: I421193f7d089584a26db629be27414d050a74337 Signed-off-by: wang_zhiqiang <wang_zhiqiang@dl.cn.nexty-ele.com>
Diffstat (limited to 'app')
-rw-r--r--app/Onscreen.qml156
-rw-r--r--app/app.pro36
-rw-r--r--app/eventhandler.cpp191
-rw-r--r--app/eventhandler.h71
-rw-r--r--app/hmi-debug.h77
-rw-r--r--app/images/DividingLine.svg62
-rw-r--r--app/images/critical.svg146
-rw-r--r--app/images/exclamation.svg130
-rw-r--r--app/images/images.qrc10
-rw-r--r--app/images/information.svg130
-rw-r--r--app/images/question.svg130
-rw-r--r--app/main.cpp79
-rw-r--r--app/main.qml125
-rw-r--r--app/onscreenmodel.cpp90
-rw-r--r--app/onscreenmodel.h48
-rw-r--r--app/qml.qrc6
16 files changed, 1487 insertions, 0 deletions
diff --git a/app/Onscreen.qml b/app/Onscreen.qml
new file mode 100644
index 0000000..cfad090
--- /dev/null
+++ b/app/Onscreen.qml
@@ -0,0 +1,156 @@
+import QtQuick 2.0
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.0
+
+Rectangle {
+ id: mainform
+ height: 300
+ width: 1000
+ radius:2
+
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#12262E" }
+ GradientStop { position: 1.0; color: "#18899B" }
+ }
+
+ ColumnLayout {
+ anchors {
+ topMargin: 10; bottomMargin:10
+ leftMargin: 20; rightMargin: 20
+ fill: parent
+ }
+ spacing: 2
+
+ ColumnLayout {
+ id: title_part
+ anchors {
+ top: parent.top
+ left: parent.left
+ topMargin: 10
+ }
+
+ Label {
+ id: title
+ text: dsp_title
+ color: "white"
+ font.pixelSize: 32
+ font.bold: true
+ maximumLineCount: 1
+ wrapMode: Text.Wrap
+ elide: Text.ElideRight
+ horizontalAlignment: Label.AlignHCenter
+ verticalAlignment: Label.AlignVCenter
+ Layout.preferredWidth: 960
+ Layout.preferredHeight: 40
+ }
+
+ Image {
+ source: '../images/DividingLine.svg'
+ anchors.left: title.left
+ anchors.top: title.bottom
+ }
+ }
+
+ RowLayout {
+ id: contents_part
+ anchors {
+ left: parent.left; leftMargin: 20
+ right: parent.right; rightMargin: 20
+ }
+ Layout.preferredWidth: 920
+ Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
+ spacing: 10
+ Image {
+ id: dsp_mark
+ source: dsp_icon
+ Layout.maximumHeight: 120
+ Layout.maximumWidth: 120
+ }
+ Label {
+ text: dsp_contents
+ color: "white"
+ font.pixelSize: 24
+ wrapMode: Text.Wrap
+ maximumLineCount: btn_area.visible ? 4 : 5
+ elide: Text.ElideRight
+ horizontalAlignment: Label.AlignLeft
+ verticalAlignment: Label.AlignVCenter
+ Layout.preferredWidth: 780
+ Layout.preferredHeight: 160
+ }
+ }
+
+ RowLayout {
+ id: btn_area
+ spacing: 60
+ visible: btnNum > 0 ? true : false
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ }
+ Layout.preferredWidth: parent.width*0.75
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+
+ Button {
+ id: btn1
+ visible: btn1Name == "" ? false : true
+ text: btn1Name
+ onReleased: {
+ btn1.highlighted = false
+ eventHandler.onScreenReply(btn1.text)
+ }
+ onPressed: {
+ btn1.highlighted = true
+ }
+ onCanceled: {
+ btn1.highlighted = false
+ }
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ }
+
+ Button {
+ id: btn2
+ visible: btn2Name == "" ? false : true
+ text: btn2Name
+ onReleased: {
+ btn2.highlighted = false
+ eventHandler.onScreenReply(btn2.text)
+ }
+ onPressed: {
+ btn2.highlighted = true
+ }
+ onCanceled: {
+ btn2.highlighted = false
+ }
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ }
+
+ Button {
+ id: btn3
+ visible: btn3Name == "" ? false : true
+ text: btn3Name
+ onReleased: {
+ btn3.highlighted = false
+ eventHandler.onScreenReply(btn3.text)
+ }
+ onPressed: {
+ btn3.highlighted = true
+ }
+ onCanceled: {
+ btn3.highlighted = false
+ }
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ }
+ }
+
+ Rectangle {
+ id: footer
+ opacity: 0
+ width: parent.width
+ height: 5
+ anchors {
+ bottom: parent.bottom
+ }
+ }
+ }
+
+}
diff --git a/app/app.pro b/app/app.pro
new file mode 100644
index 0000000..0cc31aa
--- /dev/null
+++ b/app/app.pro
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2019 TOYOTA MOTOR CORPORATION
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+TEMPLATE = app
+TARGET = onscreenapp
+QT += quickcontrols2 quick qml
+CONFIG += c++11 link_pkgconfig
+DESTDIR = $${OUT_PWD}/../package/root/bin
+PKGCONFIG += qlibwindowmanager libhomescreen
+
+HEADERS += \
+ eventhandler.h \
+ onscreenmodel.h
+
+SOURCES += \
+ eventhandler.cpp \
+ main.cpp \
+ onscreenmodel.cpp
+
+RESOURCES += \
+ qml.qrc \
+ images/images.qrc
+
+LIBS += -ljson-c
diff --git a/app/eventhandler.cpp b/app/eventhandler.cpp
new file mode 100644
index 0000000..c33022a
--- /dev/null
+++ b/app/eventhandler.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2019 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <functional>
+#include <QUrl>
+#include <QDebug>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QQmlContext>
+#include <QtQml/QQmlApplicationEngine>
+#include <cstring>
+#include <QFileInfo>
+
+#include "eventhandler.h"
+
+const char _myrole[] = "on_screen";
+const char _parameter[] = "parameter";
+const char _replyto[] = "replyto";
+const char _button_name[] = "buttonName";
+const char _drawing_name[] = "drawing_name";
+const char _application_id[] = "application_id";
+
+
+void* EventHandler::myThis = 0;
+
+EventHandler::EventHandler(QObject *parent) :
+ QObject(parent),
+ mp_hs(nullptr),
+ mp_wm(nullptr),
+ m_dsp_sts(false)
+{
+}
+
+EventHandler::~EventHandler()
+{
+ if (mp_hs != nullptr) {
+ delete mp_hs;
+ }
+ if (mp_wm != nullptr) {
+ delete mp_wm;
+ }
+}
+
+void EventHandler::init(int port, const char *token)
+{
+ myThis = this;
+ mp_wm = new QLibWindowmanager();
+ mp_wm->init(port, token);
+
+ mp_hs = new LibHomeScreen();
+ mp_hs->init(port, token);
+
+ mp_hs->registerCallback(nullptr, EventHandler::onRep_static);
+ mp_hs->set_event_handler(LibHomeScreen::Event_ShowWindow, [this](json_object *object){
+ /*
+ {
+ "application_id": "onscreenapp",
+ "parameter": {
+ "title": "onscreen title",
+ "type": "critical,exclamation,question,information",
+ "contents": "message contents",
+ "buttons": ["button_name1", "button_name2", "button_name3"],
+ "replyto":"caller application id"
+ }
+ } */
+ HMI_DEBUG(APP_ID, "recived json message is[%s]", json_object_get_string(object));
+
+ struct json_object *param;
+ if(!json_object_object_get_ex(object, _parameter, &param)
+ || json_object_get_type(param) != json_type_object) {
+ HMI_DEBUG(APP_ID, "parameter error!");
+ return;
+ }
+
+ struct json_object *replyid;
+ const char *replyto = nullptr;
+ if(json_object_object_get_ex(param, _replyto, &replyid))
+ replyto = json_object_get_string(replyid);
+ if(replyto == nullptr) {
+ HMI_DEBUG(APP_ID, "received replyto is null!");
+ return;
+ }
+ m_req = qMakePair(QString(replyto), QString(json_object_to_json_string(param)));
+
+ if (this->getDisplayStatus() == HIDING) {
+ this->activateWindow(_myrole, "on_screen");
+ }
+ else if(this->getDisplayStatus() == SHOWING) {
+ this->setDisplayStatus(SWAPPING);
+ emit this->hideOnScreen();
+ }
+ else {
+ HMI_DEBUG(APP_ID, "onscreen swapping!");
+ }
+ HMI_DEBUG(APP_ID, "received showWindow event, end!, line=%d", __LINE__);
+ });
+
+ mp_hs->set_event_handler(LibHomeScreen::Event_HideWindow, [this](json_object *object){
+ emit this->hideOnScreen();
+ HMI_DEBUG(APP_ID, "hideWindow json_object=%s", json_object_get_string(object));
+ });
+
+ if (mp_wm->requestSurface(_myrole) != 0) {
+ HMI_DEBUG(APP_ID, "!!!!LayoutHandler requestSurface Failed!!!!!");
+ exit(EXIT_FAILURE);
+ }
+
+ mp_wm->set_event_handler(QLibWindowmanager::Event_SyncDraw, [this](json_object *object) {
+ HMI_DEBUG(APP_ID, "Surface %s got syncDraw!", _myrole);
+ this->mp_wm->endDraw(QString(_myrole));
+ });
+
+ mp_wm->set_event_handler(QLibWindowmanager::Event_Visible, [this](json_object *object) {
+ struct json_object *value;
+ json_object_object_get_ex(object, _drawing_name, &value);
+ const char *name = json_object_get_string(value);
+ if(!strcasecmp(_myrole, name)){
+ this->setDisplayStatus(SHOWING);
+ this->m_dsp = this->m_req;
+ this->updateModel(QVariant(this->m_dsp.second));
+ emit this->showOnScreen();
+ }
+
+ HMI_DEBUG(APP_ID, "Event_Visible kKeyDrawingName = %s", name);
+ });
+
+ mp_wm->set_event_handler(QLibWindowmanager::Event_Invisible, [this](json_object *object) {
+ struct json_object *value;
+ json_object_object_get_ex(object, _drawing_name, &value);
+ const char *name = json_object_get_string(value);
+
+ HMI_DEBUG(APP_ID, "Event_Invisible kKeyDrawingName = %s", name);
+ });
+
+ HMI_DEBUG(APP_ID, "LayoutHander::init() finished.");
+}
+
+void EventHandler::onRep_static(struct json_object* reply_contents)
+{
+ static_cast<EventHandler*>(EventHandler::myThis)->onRep(reply_contents);
+}
+
+void EventHandler::onRep(struct json_object* reply_contents)
+{
+ const char* str = json_object_to_json_string(reply_contents);
+ HMI_DEBUG(APP_ID, "EventHandler::onReply %s", str);
+}
+
+void EventHandler::activateWindow(const char *role, const char *area)
+{
+ HMI_DEBUG(APP_ID, "EventHandler::activateWindow()");
+ mp_wm->activateWindow(role, area);
+}
+
+void EventHandler::deactivateWindow()
+{
+ HMI_DEBUG(APP_ID, "EventHandler::deactivateWindow()");
+ if(getDisplayStatus() == SWAPPING) {
+ setDisplayStatus(SHOWING);
+ m_dsp = m_req;
+ updateModel(QVariant(this->m_dsp.second));
+ emit showOnScreen();
+ }
+ else {
+ this->setDisplayStatus(HIDING);
+ mp_wm->deactivateWindow(_myrole);
+ }
+}
+
+void EventHandler::onScreenReply(const QString &btn_name)
+{
+ HMI_DEBUG(APP_ID, "EventHandler::onScreenReply(),btn_name=%s", btn_name.toStdString().c_str());
+ emit this->hideOnScreen();
+
+ struct json_object* j_param = json_object_new_object();
+ json_object_object_add(j_param, _button_name, json_object_new_string(btn_name.toStdString().c_str()));
+ mp_hs->replyShowWindow(m_dsp.first.toStdString().c_str(), j_param);
+}
diff --git a/app/eventhandler.h b/app/eventhandler.h
new file mode 100644
index 0000000..567c8a9
--- /dev/null
+++ b/app/eventhandler.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HOMESCREENHANDLER_H
+#define HOMESCREENHANDLER_H
+
+#include <QObject>
+#include <string>
+#include <QVariant>
+#include <QPair>
+#include <libhomescreen.hpp>
+#include <qlibwindowmanager.h>
+#include "hmi-debug.h"
+
+#define APP_ID "onscreenapp"
+
+class QQmlApplicationEngine;
+
+class EventHandler : public QObject
+{
+ Q_OBJECT
+public:
+ explicit EventHandler(QObject *parent = 0);
+ ~EventHandler();
+ EventHandler(const EventHandler&) = delete;
+ EventHandler& operator=(const EventHandler&) = delete;
+
+ void init(int port, const char* token);
+ void onRep(struct json_object* reply_contents);
+
+ static void* myThis;
+ static void onRep_static(struct json_object* reply_contents);
+
+ Q_INVOKABLE void deactivateWindow();
+ Q_INVOKABLE void onScreenReply(const QString &btn_name);
+
+signals:
+ void updateModel(QVariant data);
+ void showOnScreen();
+ void hideOnScreen();
+
+private:
+ enum {
+ HIDING = 0,
+ SHOWING,
+ SWAPPING
+ };
+
+ int getDisplayStatus() {return m_dsp_sts;}
+ void setDisplayStatus(int sts) {m_dsp_sts = sts;}
+ void activateWindow(const char *role, const char *area = "normal.full");
+
+ LibHomeScreen *mp_hs;
+ QLibWindowmanager* mp_wm;
+ QPair<QString, QString> m_req, m_dsp;
+ int m_dsp_sts = HIDING;
+};
+#endif // HOMESCREENHANDLER_H
diff --git a/app/hmi-debug.h b/app/hmi-debug.h
new file mode 100644
index 0000000..5178aa5
--- /dev/null
+++ b/app/hmi-debug.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HMI_DEBUG_H__
+#define __HMI_DEBUG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <time.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+enum LOG_LEVEL{
+ LOG_LEVEL_NONE = 0,
+ LOG_LEVEL_ERROR,
+ LOG_LEVEL_WARNING,
+ LOG_LEVEL_NOTICE,
+ LOG_LEVEL_INFO,
+ LOG_LEVEL_DEBUG,
+ LOG_LEVEL_MAX = LOG_LEVEL_DEBUG
+};
+
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+#define HMI_ERROR(prefix, args,...) _HMI_LOG(LOG_LEVEL_ERROR, __FILENAME__, __FUNCTION__, __LINE__, prefix, args, ##__VA_ARGS__)
+#define HMI_WARNING(prefix, args,...) _HMI_LOG(LOG_LEVEL_WARNING, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__)
+#define HMI_NOTICE(prefix, args,...) _HMI_LOG(LOG_LEVEL_NOTICE, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__)
+#define HMI_INFO(prefix, args,...) _HMI_LOG(LOG_LEVEL_INFO, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__)
+#define HMI_DEBUG(prefix, args,...) _HMI_LOG(LOG_LEVEL_DEBUG, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__)
+
+static char ERROR_FLAG[6][20] = {"NONE", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"};
+
+static void _HMI_LOG(enum LOG_LEVEL level, const char* file, const char* func, const int line, const char* prefix, const char* log, ...)
+{
+ const int log_level = (getenv("USE_HMI_DEBUG") == NULL)?LOG_LEVEL_ERROR:atoi(getenv("USE_HMI_DEBUG"));
+ if(log_level < level)
+ {
+ return;
+ }
+
+ char *message;
+ struct timespec tp;
+ unsigned int time;
+
+ clock_gettime(CLOCK_REALTIME, &tp);
+ time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
+
+ va_list args;
+ va_start(args, log);
+ if (log == NULL || vasprintf(&message, log, args) < 0)
+ message = NULL;
+ fprintf(stderr, "[%10.3f] [%s %s] [%s, %s(), Line:%d] >>> %s \n", time / 1000.0, prefix, ERROR_FLAG[level], file, func, line, message);
+ va_end(args);
+ free(message);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__HMI_DEBUG_H__
diff --git a/app/images/DividingLine.svg b/app/images/DividingLine.svg
new file mode 100644
index 0000000..788256c
--- /dev/null
+++ b/app/images/DividingLine.svg
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg12699"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ width="960"
+ height="1"
+ viewBox="0 0 960 1"
+ sodipodi:docname="DividingLine-960.svg">
+ <metadata
+ id="metadata12705">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs12703" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1615"
+ inkscape:window-height="917"
+ id="namedview12701"
+ showgrid="false"
+ inkscape:zoom="1"
+ inkscape:cx="403.34338"
+ inkscape:cy="-3.7733099"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg12699" />
+ <image
+ width="960"
+ height="1"
+ preserveAspectRatio="none"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvoAAAABCAIAAAAgt51xAAAAAXNSR0IArs4c6QAAAARnQU1BAACx jwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAbSURBVEhLY1g2CkbBKBgFo2AUjIJRMIzBsmUA zyfKoJIKS6oAAAAASUVORK5CYII= "
+ id="image12707"
+ x="0"
+ y="1.3877788e-17" />
+</svg>
diff --git a/app/images/critical.svg b/app/images/critical.svg
new file mode 100644
index 0000000..e2df6fc
--- /dev/null
+++ b/app/images/critical.svg
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="320"
+ height="320"
+ viewBox="0 0 320 320.00001"
+ id="svg5033"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="critical.svg">
+ <defs
+ id="defs5035">
+ <linearGradient
+ gradientTransform="matrix(1.0123741,0,0,1.0052855,226.82647,753.70831)"
+ inkscape:collect="always"
+ xlink:href="#SVGID_36_"
+ id="linearGradient5005"
+ x1="-125.27629"
+ y1="217.50423"
+ x2="-4.2735882"
+ y2="57.848095"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="SVGID_36_"
+ gradientUnits="userSpaceOnUse"
+ x1="4.0481"
+ y1="287.94919"
+ x2="320.4859"
+ y2="-15.4029"
+ gradientTransform="matrix(1,0.00546456,-0.00546456,1,-2.0192,-3.0212)">
+ <stop
+ offset="0"
+ style="stop-color:#54d187;stop-opacity:0.90588236"
+ id="stop300" />
+ <stop
+ id="stop9348"
+ style="stop-color:#12c1bb;stop-opacity:0.65882355"
+ offset="0.51862437" />
+ <stop
+ offset="1"
+ style="stop-color:#055658;stop-opacity:0.38431373"
+ id="stop302" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffa4ff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.7480469"
+ inkscape:cx="10.563348"
+ inkscape:cy="199.74517"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1615"
+ inkscape:window-height="1026"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ units="px"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ position="160,377.00001"
+ orientation="1,0"
+ id="guide5666" />
+ <sodipodi:guide
+ position="60,448.00001"
+ orientation="1,0"
+ id="guide5668" />
+ <sodipodi:guide
+ position="260,414.00001"
+ orientation="1,0"
+ id="guide5670" />
+ <sodipodi:guide
+ position="-44.5,265.00001"
+ orientation="0,1"
+ id="guide10700" />
+ <sodipodi:guide
+ position="-36.5,60.000002"
+ orientation="0,1"
+ id="guide10702" />
+ <sodipodi:guide
+ position="-133.64318,165.46299"
+ orientation="0,1"
+ id="guide10704" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata5038">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-732.36216)">
+ <path
+ style="fill:#00ffbd;fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 160.42857,785.99962 A 104.88141,105.22039 0 0 0 55.54771,891.21837 104.88141,105.22039 0 0 0 160.42857,996.43908 104.88141,105.22039 0 0 0 265.30943,891.21837 104.88141,105.22039 0 0 0 160.42857,785.99962 Z m -0.33984,3.38867 A 101.83055,101.66108 0 0 1 261.92076,891.0504 101.83055,101.66108 0 0 1 160.08873,992.71056 101.83055,101.66108 0 0 1 58.25865,891.0504 101.83055,101.66108 0 0 1 160.08873,789.38829 Z"
+ id="path4374"
+ inkscape:connector-curvature="0" />
+ <ellipse
+ style="opacity:0.77;fill:url(#linearGradient5005);fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;fill-rule:nonzero"
+ id="path4417"
+ cx="160.24997"
+ cy="891.04053"
+ rx="102.26696"
+ ry="101.89165" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect4394"
+ width="166.1017"
+ height="18.983051"
+ x="-600.41077"
+ y="733.77344"
+ transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,0,0)" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect4394-6"
+ width="166.1017"
+ height="18.983051"
+ x="659.83057"
+ y="508.15701"
+ transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
+ </g>
+</svg>
diff --git a/app/images/exclamation.svg b/app/images/exclamation.svg
new file mode 100644
index 0000000..c43ebdd
--- /dev/null
+++ b/app/images/exclamation.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="320"
+ height="320"
+ viewBox="0 0 320 320.00001"
+ id="svg5033"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="exclamation.svg">
+ <defs
+ id="defs5035">
+ <linearGradient
+ gradientTransform="matrix(1.0123741,0,0,1.0052855,226.82647,753.70831)"
+ inkscape:collect="always"
+ xlink:href="#SVGID_36_"
+ id="linearGradient5005"
+ x1="-125.27629"
+ y1="217.50423"
+ x2="-4.2735882"
+ y2="57.848095"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="SVGID_36_"
+ gradientUnits="userSpaceOnUse"
+ x1="4.0481"
+ y1="287.94919"
+ x2="320.4859"
+ y2="-15.4029"
+ gradientTransform="matrix(1,0.00546456,-0.00546456,1,-2.0192,-3.0212)">
+ <stop
+ offset="0"
+ style="stop-color:#54d187;stop-opacity:0.90588236"
+ id="stop300" />
+ <stop
+ id="stop9348"
+ style="stop-color:#12c1bb;stop-opacity:0.65882355"
+ offset="0.51862437" />
+ <stop
+ offset="1"
+ style="stop-color:#055658;stop-opacity:0.38431373"
+ id="stop302" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffa4ff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.6505829"
+ inkscape:cx="210.27412"
+ inkscape:cy="19.42679"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1615"
+ inkscape:window-height="1026"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ units="px"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ position="160,377.00001"
+ orientation="1,0"
+ id="guide5666" />
+ <sodipodi:guide
+ position="60,448.00001"
+ orientation="1,0"
+ id="guide5668" />
+ <sodipodi:guide
+ position="260,414.00001"
+ orientation="1,0"
+ id="guide5670" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata5038">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-732.36216)">
+ <path
+ style="fill:#00ffbd;fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 160.42857,785.99962 A 104.88141,105.22039 0 0 0 55.54771,891.21837 104.88141,105.22039 0 0 0 160.42857,996.43908 104.88141,105.22039 0 0 0 265.30943,891.21837 104.88141,105.22039 0 0 0 160.42857,785.99962 Z m -0.33984,3.38867 A 101.83055,101.66108 0 0 1 261.92076,891.0504 101.83055,101.66108 0 0 1 160.08873,992.71056 101.83055,101.66108 0 0 1 58.25865,891.0504 101.83055,101.66108 0 0 1 160.08873,789.38829 Z"
+ id="path4374"
+ inkscape:connector-curvature="0" />
+ <ellipse
+ style="opacity:0.77;fill:url(#linearGradient5005);fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;fill-rule:nonzero"
+ id="path4417"
+ cx="160.24997"
+ cy="891.04053"
+ rx="102.26696"
+ ry="101.89165" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:196.94758606px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ x="112.91733"
+ y="1033.4916"
+ id="text5620"
+ sodipodi:linespacing="125%"
+ transform="scale(1.0772696,0.92827274)"><tspan
+ sodipodi:role="line"
+ id="tspan5622"
+ x="112.91733"
+ y="1033.4916">!</tspan></text>
+ </g>
+</svg>
diff --git a/app/images/images.qrc b/app/images/images.qrc
new file mode 100644
index 0000000..842a9fb
--- /dev/null
+++ b/app/images/images.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource prefix="/images">
+ <file>DividingLine.svg</file>
+ <file>critical.svg</file>
+ <file>exclamation.svg</file>
+ <file>information.svg</file>
+ <file>question.svg</file>
+ </qresource>
+ <qresource prefix="/"/>
+</RCC>
diff --git a/app/images/information.svg b/app/images/information.svg
new file mode 100644
index 0000000..44b0ef8
--- /dev/null
+++ b/app/images/information.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="320"
+ height="320"
+ viewBox="0 0 320 320.00001"
+ id="svg5033"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="information.svg">
+ <defs
+ id="defs5035">
+ <linearGradient
+ gradientTransform="matrix(1.0123741,0,0,1.0052855,226.82647,753.70831)"
+ inkscape:collect="always"
+ xlink:href="#SVGID_36_"
+ id="linearGradient5005"
+ x1="-125.27629"
+ y1="217.50423"
+ x2="-4.2735882"
+ y2="57.848095"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="SVGID_36_"
+ gradientUnits="userSpaceOnUse"
+ x1="4.0481"
+ y1="287.94919"
+ x2="320.4859"
+ y2="-15.4029"
+ gradientTransform="matrix(1,0.00546456,-0.00546456,1,-2.0192,-3.0212)">
+ <stop
+ offset="0"
+ style="stop-color:#54d187;stop-opacity:0.90588236"
+ id="stop300" />
+ <stop
+ id="stop9348"
+ style="stop-color:#12c1bb;stop-opacity:0.65882355"
+ offset="0.51862437" />
+ <stop
+ offset="1"
+ style="stop-color:#055658;stop-opacity:0.38431373"
+ id="stop302" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffa4ff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.1606835"
+ inkscape:cx="150.68658"
+ inkscape:cy="151.76859"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1615"
+ inkscape:window-height="1026"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ units="px"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ position="160,377.00001"
+ orientation="1,0"
+ id="guide5666" />
+ <sodipodi:guide
+ position="59.494972,568.63465"
+ orientation="1,0"
+ id="guide5668" />
+ <sodipodi:guide
+ position="259.71844,528.58996"
+ orientation="1,0"
+ id="guide5670" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata5038">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-732.36216)">
+ <path
+ style="fill:#00ffbd;fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 160.42857,785.99962 A 104.88141,105.22039 0 0 0 55.54771,891.21837 104.88141,105.22039 0 0 0 160.42857,996.43908 104.88141,105.22039 0 0 0 265.30943,891.21837 104.88141,105.22039 0 0 0 160.42857,785.99962 Z m -0.33984,3.38867 A 101.83055,101.66108 0 0 1 261.92076,891.0504 101.83055,101.66108 0 0 1 160.08873,992.71056 101.83055,101.66108 0 0 1 58.25865,891.0504 101.83055,101.66108 0 0 1 160.08873,789.38829 Z"
+ id="path4374"
+ inkscape:connector-curvature="0" />
+ <ellipse
+ style="opacity:0.77;fill:url(#linearGradient5005);fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;fill-rule:nonzero"
+ id="path4417"
+ cx="160.24997"
+ cy="891.04053"
+ rx="102.26696"
+ ry="101.89165" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:196.94758606px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ x="122.20006"
+ y="1033.4916"
+ id="text5620"
+ sodipodi:linespacing="125%"
+ transform="scale(1.0772696,0.92827274)"><tspan
+ sodipodi:role="line"
+ id="tspan5622"
+ x="122.20006"
+ y="1033.4916">i</tspan></text>
+ </g>
+</svg>
diff --git a/app/images/question.svg b/app/images/question.svg
new file mode 100644
index 0000000..7d55a46
--- /dev/null
+++ b/app/images/question.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="320"
+ height="320"
+ viewBox="0 0 320 320.00001"
+ id="svg5033"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="question.svg">
+ <defs
+ id="defs5035">
+ <linearGradient
+ gradientTransform="matrix(1.0123741,0,0,1.0052855,226.82647,753.70831)"
+ inkscape:collect="always"
+ xlink:href="#SVGID_36_"
+ id="linearGradient5005"
+ x1="-125.27629"
+ y1="217.50423"
+ x2="-4.2735882"
+ y2="57.848095"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="SVGID_36_"
+ gradientUnits="userSpaceOnUse"
+ x1="4.0481"
+ y1="287.94919"
+ x2="320.4859"
+ y2="-15.4029"
+ gradientTransform="matrix(1,0.00546456,-0.00546456,1,-2.0192,-3.0212)">
+ <stop
+ offset="0"
+ style="stop-color:#54d187;stop-opacity:0.90588236"
+ id="stop300" />
+ <stop
+ id="stop9348"
+ style="stop-color:#12c1bb;stop-opacity:0.65882355"
+ offset="0.51862437" />
+ <stop
+ offset="1"
+ style="stop-color:#055658;stop-opacity:0.38431373"
+ id="stop302" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffa4ff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.2360558"
+ inkscape:cx="192.682"
+ inkscape:cy="132.16195"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1615"
+ inkscape:window-height="1026"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ units="px"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ position="160,377.00001"
+ orientation="1,0"
+ id="guide5666" />
+ <sodipodi:guide
+ position="60,448.00001"
+ orientation="1,0"
+ id="guide5668" />
+ <sodipodi:guide
+ position="260,414.00001"
+ orientation="1,0"
+ id="guide5670" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata5038">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-732.36216)">
+ <path
+ style="fill:#00ffbd;fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 160.42857,785.99962 A 104.88141,105.22039 0 0 0 55.54771,891.21837 104.88141,105.22039 0 0 0 160.42857,996.43908 104.88141,105.22039 0 0 0 265.30943,891.21837 104.88141,105.22039 0 0 0 160.42857,785.99962 Z m -0.33984,3.38867 A 101.83055,101.66108 0 0 1 261.92076,891.0504 101.83055,101.66108 0 0 1 160.08873,992.71056 101.83055,101.66108 0 0 1 58.25865,891.0504 101.83055,101.66108 0 0 1 160.08873,789.38829 Z"
+ id="path4374"
+ inkscape:connector-curvature="0" />
+ <ellipse
+ style="opacity:0.77;fill:url(#linearGradient5005);fill-opacity:1;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;fill-rule:nonzero"
+ id="path4417"
+ cx="160.24997"
+ cy="891.04053"
+ rx="102.26696"
+ ry="101.89165" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:196.94758606px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ x="101.77805"
+ y="1033.4916"
+ id="text5620"
+ sodipodi:linespacing="125%"
+ transform="scale(1.0772696,0.92827274)"><tspan
+ sodipodi:role="line"
+ id="tspan5622"
+ x="101.77805"
+ y="1033.4916">?</tspan></text>
+ </g>
+</svg>
diff --git a/app/main.cpp b/app/main.cpp
new file mode 100644
index 0000000..007711c
--- /dev/null
+++ b/app/main.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <QGuiApplication>
+#include <QCommandLineParser>
+#include <QtGui/QGuiApplication>
+#include <QtQml/QQmlApplicationEngine>
+#include <QtQml/QQmlContext>
+#include <QtQml/qqml.h>
+#include <QQuickWindow>
+#include <QtQuickControls2/QQuickStyle>
+
+#include "eventhandler.h"
+#include "onscreenmodel.h"
+
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QCoreApplication::setOrganizationDomain("LinuxFoundation");
+ QCoreApplication::setOrganizationName("AutomotiveGradeLinux");
+ QCoreApplication::setApplicationName("Onscreenapp");
+ QCoreApplication::setApplicationVersion("0.1.0");
+
+ QQuickStyle::setStyle("AGL");
+
+ QCommandLineParser parser;
+ parser.addPositionalArgument("port", app.translate("main", "port for binding"));
+ parser.addPositionalArgument("secret", app.translate("main", "secret for binding"));
+ parser.addHelpOption();
+ parser.addVersionOption();
+ parser.process(app);
+ QStringList positionalArguments = parser.positionalArguments();
+
+ int port = 1700;
+ QString token = "wm";
+
+ if (positionalArguments.length() == 2) {
+ port = positionalArguments.takeFirst().toInt();
+ token = positionalArguments.takeFirst();
+ }
+
+ HMI_DEBUG(APP_ID, "port = %d, token = %s", port, token.toStdString().c_str());
+
+ QQmlApplicationEngine engine;
+ EventHandler *eventHandler = new EventHandler();
+ eventHandler->init(port, token.toStdString().c_str());
+ engine.rootContext()->setContextProperty("eventHandler", eventHandler);
+ qmlRegisterType<OnScreenModel>("OnScreenModel", 1, 0, "OnScreenModel");
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+ if (engine.rootObjects().isEmpty()) {
+ HMI_DEBUG(APP_ID, "Fatal Error, rootObject is empty!");
+ return -1;
+ }
+
+ QObject *root = engine.rootObjects().first();
+ QQuickWindow *window = qobject_cast<QQuickWindow *>(root);
+ QObject::connect(eventHandler, SIGNAL(updateModel(QVariant)), window, SLOT(setOnScreenModel(QVariant)));
+ QObject::connect(eventHandler, SIGNAL(showOnScreen()), window, SLOT(showOnScreen()));
+ QObject::connect(eventHandler, SIGNAL(hideOnScreen()), window, SLOT(hideOnScreen()));
+
+ HMI_DEBUG(APP_ID, "onscreenapp started!");
+ return app.exec();
+}
+
diff --git a/app/main.qml b/app/main.qml
new file mode 100644
index 0000000..99d50f8
--- /dev/null
+++ b/app/main.qml
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import QtQuick 2.6
+import QtQuick.Window 2.2
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.0
+import AGL.Demo.Controls 1.0
+import OnScreenModel 1.0
+
+Window {
+ id: root
+ flags: Qt.FramelessWindowHint
+ visible: true
+ x: 0
+ y: 218
+ width: 1080
+ height: 1488
+ color: '#00000000'
+
+ Onscreen {
+ id: ons
+ anchors.centerIn: parent
+ visible: true
+ scale: 0
+
+ property string dsp_sts: "hide"
+ property string dsp_title: ""
+ property string dsp_icon: ""
+ property string dsp_contents: ""
+ property int btnNum: 0
+ property string btn1Name: ""
+ property string btn2Name: ""
+ property string btn3Name: ""
+
+ states: [
+ State {
+ name: 'active'
+ when: ons.dsp_sts == "show"
+ PropertyChanges {
+ target: ons
+ scale: 1
+ z: 1
+ }
+ },
+ State {
+ name: 'inactive'
+ when: ons.dsp_sts == "hide"
+ PropertyChanges {
+ target: ons
+ scale: 0
+ z: -1
+ }
+ }
+ ]
+ transitions: Transition {
+ NumberAnimation {
+ properties: 'scale';
+ duration: 300;
+ easing.type: Easing.Linear
+ alwaysRunToEnd: true
+ }
+ }
+ }
+
+ OnScreenModel {
+ id: onscreenModel
+ }
+
+ Timer {
+ id: ons_timer
+ interval: 3000
+ onTriggered: {
+ hideOnScreen();
+ clearOnScreenModel();
+ }
+ }
+
+ Connections {
+ target: ons
+ onScaleChanged : {
+ if(ons.scale == 0) {
+ console.log(qsTr('hide animation finished'));
+ eventHandler.deactivateWindow();
+ }
+ }
+ }
+
+ function showOnScreen() {
+ console.log(qsTr('show onscreenapp'));
+ ons.dsp_title = onscreenModel.getTitle()
+ ons.dsp_icon = "../images/" + onscreenModel.getType() + ".svg"
+ ons.dsp_contents = onscreenModel.getContents()
+ ons.btnNum = onscreenModel.buttonNum()
+ ons.btn1Name = onscreenModel.buttonName(0)
+ ons.btn2Name = onscreenModel.buttonName(1)
+ ons.btn3Name = onscreenModel.buttonName(2)
+ ons_timer.running = ons.btnNum > 0 ? false : true
+ ons.dsp_sts = "show"
+ }
+
+ function hideOnScreen() {
+ console.log(qsTr('hide onscreenapp'));
+ ons.dsp_sts = "hide"
+ ons_timer.running = false
+ }
+
+ function setOnScreenModel(data) {
+ console.log(qsTr('onscreenapp >>> setModel status: ' + data));
+ onscreenModel.setModel(data)
+ }
+}
diff --git a/app/onscreenmodel.cpp b/app/onscreenmodel.cpp
new file mode 100644
index 0000000..184d1a6
--- /dev/null
+++ b/app/onscreenmodel.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "onscreenmodel.h"
+#include "hmi-debug.h"
+#include <json-c/json.h>
+
+const char _modelName[] = "OnScreenModel";
+const char _title[] = "title";
+const char _type[] = "type";
+const char _contents[] = "contents";
+const char _buttons[] = "buttons";
+
+
+void OnScreenModel::setModel(QVariant data)
+{
+ HMI_DEBUG(_modelName, "setModel start!");
+ clearModel();
+ struct json_object *j_title = nullptr, *j_type = nullptr, *j_contents = nullptr, *j_buttons = nullptr;
+ struct json_object *j_param = json_tokener_parse(data.toString().toStdString().c_str());
+ if(json_object_object_get_ex(j_param, _title, &j_title)) {
+ m_title = json_object_get_string(j_title);
+ }
+ else {
+ HMI_DEBUG(_modelName, "title input is null");
+ }
+
+ if(json_object_object_get_ex(j_param, _type, &j_type)) {
+ m_type = json_object_get_string(j_type);
+ }
+ else {
+ HMI_DEBUG(_modelName, "type input is null");
+ }
+
+ if(json_object_object_get_ex(j_param, _contents, &j_contents)) {
+ m_contents = json_object_get_string(j_contents);
+ }
+ else {
+ HMI_DEBUG(_modelName, "contents input is null");
+ }
+
+ if(json_object_object_get_ex(j_param, _buttons, &j_buttons)) {
+ if(json_object_get_type(j_buttons) != json_type_array) {
+ HMI_DEBUG(_modelName, "buttons josn type isn't array!");
+ }
+ else {
+ m_buttons.clear();
+ int len = json_object_array_length(j_buttons);
+ struct json_object *json_tmp = nullptr;
+ for (int i = 0; i < len; i++) {
+ json_tmp = json_object_array_get_idx(j_buttons, i);
+ m_buttons << QString(json_object_get_string(json_tmp));
+ }
+ }
+ }
+ else {
+ HMI_DEBUG("OnScreenModel", "buttons input is null");
+ }
+ HMI_DEBUG(_modelName, "setModel end!titile=%s,type=%s,contents=%s,btnNum=%d",
+ m_title.toStdString().c_str(), m_type.toStdString().c_str(), m_contents.toStdString().c_str(), m_buttons.size());
+}
+
+QString OnScreenModel::buttonName(int index) const
+{
+ if(index >= m_buttons.size())
+ return QString("");
+ else
+ return m_buttons[index];
+}
+
+void OnScreenModel::clearModel(void)
+{
+ m_title = "";
+ m_type = "";
+ m_contents = "";
+ m_buttons.clear();
+}
diff --git a/app/onscreenmodel.h b/app/onscreenmodel.h
new file mode 100644
index 0000000..e12b269
--- /dev/null
+++ b/app/onscreenmodel.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ONSCREENMODEL_H
+#define ONSCREENMODEL_H
+
+#include <QObject>
+#include <QVariant>
+#include <QStringList>
+
+
+class OnScreenModel : public QObject
+{
+ Q_OBJECT
+public:
+ explicit OnScreenModel(QObject *parent = nullptr){}
+ ~OnScreenModel() = default;
+
+ Q_INVOKABLE QString getTitle(void) const {return m_title;}
+ Q_INVOKABLE QString getType(void) const {return m_type;}
+ Q_INVOKABLE QString getContents(void) const {return m_contents;}
+ Q_INVOKABLE int buttonNum(void) const {return m_buttons.size();}
+ Q_INVOKABLE QString buttonName(int index) const;
+ Q_INVOKABLE void setModel(QVariant data);
+
+private:
+ void clearModel(void);
+
+ QString m_title;
+ QString m_type;
+ QString m_contents;
+ QStringList m_buttons;
+};
+
+#endif // ONSCREENMODEL_H
diff --git a/app/qml.qrc b/app/qml.qrc
new file mode 100644
index 0000000..bad4ade
--- /dev/null
+++ b/app/qml.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>Onscreen.qml</file>
+ </qresource>
+</RCC>