warehouse for ces2019
[apps/onscreenapp.git] / app / src / serverappmodel.cpp
1 /*
2  * Copyright (C) 2016 The Qt Company Ltd.
3  * Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH
4  * Copyright (c) 2018 TOYOTA MOTOR CORPORATION
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include "serverappmodel.h"
20 #include <QtCore/QJsonArray>
21 #include <QtCore/QJsonDocument>
22 #include "afm_user_daemon_proxy.h"
23 #include "httpclient.h"
24
25 #include "hmi-debug.h"
26
27 extern org::AGL::afm::user* afm_user_daemon_proxy;
28
29 ServerAppModel::ServerAppModel(QObject* parent) : QAbstractListModel(parent) {
30   // this->getAppPage(0, PAGE_SIZE);
31   connect(afm_user_daemon_proxy, &org::AGL::afm::user::changed, this,
32           &ServerAppModel::appChanged);
33 }
34
35 ServerAppModel::~ServerAppModel() {}
36
37 int ServerAppModel::rowCount(const QModelIndex& parent) const {
38   if (parent.isValid())
39     return 0;
40
41   return this->applist.count();
42 }
43
44 QVariant ServerAppModel::data(const QModelIndex& index, int role) const {
45   QVariant ret;
46   if (!index.isValid())
47     return ret;
48
49   switch (role) {
50     case IconRole:
51       ret = this->applist[index.row()].iconPath();
52       break;
53     case NameRole:
54       ret = this->applist[index.row()].name();
55       break;
56     case IdRole:
57       ret = this->applist[index.row()].id();
58       break;
59     case VersionRole:
60       ret = this->applist[index.row()].version();
61       break;
62     case DescriptionRole:
63       ret = this->applist[index.row()].description();
64       break;
65     case AuthorRole:
66       ret = this->applist[index.row()].author();
67       break;
68     case ServerIdRole:
69       ret = this->applist[index.row()].serverId();
70       break;
71     case CategoryNameRole:
72       ret = this->applist[index.row()].categoryName();
73       break;
74     case CreatedTimeRole:
75       ret = this->applist[index.row()].createdTime();
76       break;
77     case StateRole:
78       ret = this->applist[index.row()].state();
79       break;
80     case StateTextRole:
81       switch (this->applist[index.row()].state()) {
82         case AppInfo::Install:
83           ret = "Install";
84           break;
85         case AppInfo::Update:
86           ret = "Update";
87           break;
88         case AppInfo::Launch:
89           ret = "Launch";
90           break;
91         case AppInfo::Downloading:
92           ret = "Downloading";
93           break;
94         case AppInfo::Installing:
95           ret = "Installing";
96           break;
97         default:
98           break;
99       }
100       break;
101     case ProgressRole:
102       ret = this->applist[index.row()].progress();
103       break;
104     default:
105       break;
106   }
107
108   return ret;
109 }
110
111 QHash<int, QByteArray> ServerAppModel::roleNames() const {
112   QHash<int, QByteArray> roles;
113   roles[IconRole] = "icon";
114   roles[NameRole] = "name";
115   roles[IdRole] = "id";
116   roles[VersionRole] = "version";
117   roles[DescriptionRole] = "description";
118   roles[AuthorRole] = "author";
119   roles[ServerIdRole] = "appid";
120   roles[CategoryNameRole] = "category";
121   roles[CreatedTimeRole] = "createdtime";
122   roles[StateRole] = "state";
123   roles[StateTextRole] = "statetext";
124   roles[ProgressRole] = "progress";
125   return roles;
126 }
127
128 QString ServerAppModel::id(int i) const {
129   return data(index(i), IdRole).toString();
130 }
131
132 QString ServerAppModel::name(int i) const {
133   return data(index(i), NameRole).toString();
134 }
135
136 QString ServerAppModel::stateText(int i) const {
137   return data(index(i), StateTextRole).toString();
138 }
139
140 int ServerAppModel::launch(const QString& application) {
141   int result = -1;
142   HMI_DEBUG("launch", "ApplicationLauncher launch %s.",
143             application.toStdString().c_str());
144
145   result = afm_user_daemon_proxy->start(application).value().toInt();
146   HMI_DEBUG("launch", "ApplicationLauncher pid: %d.", result);
147
148   return result;
149 }
150
151 void ServerAppModel::appChanged(const QString& info) {
152   QJsonDocument japps = QJsonDocument::fromJson(info.toUtf8());
153   QJsonObject const& jso = japps.object();
154   QString operation = jso["operation"].toString();
155   QString id = jso["data"].toString();
156   if (operation == "uninstall") {
157     for (int i = 0; i < applist.size(); ++i) {
158       if (applist.at(i).id() == id) {
159         beginResetModel();
160         applist[i].setState(AppInfo::Install);
161         endResetModel();
162         break;
163       }
164     }
165   }
166 }
167
168 void ServerAppModel::install(int index) {
169   AppInfo& appinfo = applist[index];
170
171   beginResetModel();
172   appinfo.setState(AppInfo::Downloading);
173   endResetModel();
174
175   QString url =
176       getWgtUrl(appinfo.wgtPath());
177   HttpClient client(url);
178
179   client.download(
180       getDownloadFilePath(appinfo.fileName()),
181       [this, &appinfo](const QString& result) {
182         this->beginResetModel();
183         appinfo.setState(AppInfo::Installing);
184         this->endResetModel();
185
186         QTimer::singleShot(3000, this, [this, &appinfo] {
187           QString installResult = afm_user_daemon_proxy->install(
188               getDownloadFilePath(appinfo.fileName()));
189
190           this->beginResetModel();
191           appinfo.setState(installResult.isEmpty() ? AppInfo::Install
192                                                    : AppInfo::Launch);
193           appinfo.setProgress(0.0);
194           this->endResetModel();
195         });
196       },
197       [this, &appinfo](const QString& error) {
198         HMI_ERROR("ERROR", "%s", error.toStdString().c_str());
199         this->beginResetModel();
200         appinfo.setState(AppInfo::Install);
201         appinfo.setProgress(0.0);
202         this->beginResetModel();
203       },
204       [this, &appinfo](const qint64 bytesReceived, const qint64 bytesTotal) {
205         qreal progressValue = ((qreal)bytesReceived / bytesTotal) * 100;
206         this->beginResetModel();
207         appinfo.setProgress(progressValue);
208         this->endResetModel();
209       });
210 }
211
212 void ServerAppModel::getPrevPage(int pageIndex) {
213   this->getAppPage(pageIndex, PAGE_SIZE, true);
214 }
215
216 void ServerAppModel::getNextPage(int pageIndex) {
217   this->getAppPage(pageIndex, PAGE_SIZE);
218 }
219
220 void ServerAppModel::setNativeApplist(const QList<AppInfo>& applist) {
221   nativeApplist.clear();
222   nativeApplist = applist;
223   checkAppState();
224 }
225
226 void ServerAppModel::checkAppState() {
227   if (applist.isEmpty() || nativeApplist.isEmpty()) {
228     return;
229   }
230
231   beginResetModel();
232
233   QList<AppInfo>::iterator it;
234   for (it = applist.begin(); it != applist.end(); ++it) {
235     QList<AppInfo>::iterator nit;
236     for (nit = nativeApplist.begin(); nit != nativeApplist.end(); ++nit) {
237       if ((*it).id() == (*nit).id()) {
238         (*it).setState((*it).version() != (*nit).version() ? AppInfo::Update
239                                                            : AppInfo::Launch);
240         break;
241       }
242     }
243   }
244
245   endResetModel();
246 }
247
248 void ServerAppModel::getAppPage(int pageIndex, int pageSize, bool isPrev) {
249   // QString url = getUrlWithPage(SERVER_API_LIST, pageIndex, pageSize)
250   //                   .append(QString("&appDeviceTypeId=%1&appDeveloper=%2")
251   //                               .arg(QString::number(0), "zhang_xu"));
252   QString url =
253       getUrlWithPage(SERVER_API_LIST, pageIndex, pageSize)
254           .append(QString("&appDeviceTypeId=%1").arg(QString::number(0)));
255   HttpClient client(url);
256
257   client.get(
258       [=](const QString& result) {
259         QJsonDocument jresult = QJsonDocument::fromJson(result.toUtf8());
260         QJsonObject const& jro = jresult.object();
261         QJsonArray const& jappList = jro["pagination_data"].toArray();
262
263         QList<AppInfo> newList;
264         for (auto const& app : jappList) {
265           QJsonObject const& jso = app.toObject();
266
267           AppInfo appinfo;
268           appinfo.readFromServer(jso);
269           newList.append(appinfo);
270         }
271
272         beginResetModel();
273         if (isPrev || jappList.size() >= PAGE_SIZE) {
274           applist.clear();
275         }
276         applist += newList;
277         endResetModel();
278
279         checkAppState();
280
281         emit requestCompleted(jappList.size(), PAGE_SIZE);
282       },
283       [=](const QString& msg) {
284         HMI_ERROR("response", "response error: %s", msg.toStdString().c_str());
285       });
286 }