/* * Copyright (C) 2016 The Qt Company Ltd. * Copyright (C) 2016, 2017 Mentor Graphics Development (Deutschland) GmbH * Copyright (c) 2018-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 "serverappmodel.h" #include #include #include "afm_user_daemon_proxy.h" #include "httpclient.h" #include "hmi-debug.h" extern org::AGL::afm::user* afm_user_daemon_proxy; ServerAppModel::ServerAppModel(QObject* parent) : QAbstractListModel(parent) { // this->getAppPage(0, PAGE_SIZE); connect(afm_user_daemon_proxy, &org::AGL::afm::user::changed, this, &ServerAppModel::appChanged); } ServerAppModel::~ServerAppModel() {} int ServerAppModel::rowCount(const QModelIndex& parent) const { if (parent.isValid()) return 0; return this->applist.count(); } QVariant ServerAppModel::data(const QModelIndex& index, int role) const { QVariant ret; if (!index.isValid()) return ret; switch (role) { case IconRole: ret = this->applist[index.row()].iconPath(); break; case NameRole: ret = this->applist[index.row()].name(); break; case IdRole: ret = this->applist[index.row()].id(); break; case VersionRole: ret = this->applist[index.row()].version(); break; case DescriptionRole: ret = this->applist[index.row()].description(); break; case AuthorRole: ret = this->applist[index.row()].author(); break; case ServerIdRole: ret = this->applist[index.row()].serverId(); break; case CategoryNameRole: ret = this->applist[index.row()].categoryName(); break; case CreatedTimeRole: ret = this->applist[index.row()].createdTime(); break; case StateRole: ret = this->applist[index.row()].state(); break; case StateTextRole: switch (this->applist[index.row()].state()) { case AppInfo::Install: ret = "Install"; break; case AppInfo::Update: ret = "Update"; break; case AppInfo::Launch: ret = "Launch"; break; case AppInfo::Downloading: ret = "Downloading"; break; case AppInfo::Installing: ret = "Installing"; break; default: break; } break; case ProgressRole: ret = this->applist[index.row()].progress(); break; default: break; } return ret; } bool ServerAppModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (!index.isValid()) return false; switch (role) { case StateRole: applist[index.row()].setState(value.toInt()); break; case ProgressRole: applist[index.row()].setProgress(value.toReal()); break; default: return false; break; } emit dataChanged(index, index); return true; } bool ServerAppModel::removeRows(int row, int count, const QModelIndex&) { QList::iterator begin = applist.begin() + row; QList::iterator end = begin + count; applist.erase(begin, end); return true; } QHash ServerAppModel::roleNames() const { QHash roles; roles[IconRole] = "icon"; roles[NameRole] = "name"; roles[IdRole] = "id"; roles[VersionRole] = "version"; roles[DescriptionRole] = "description"; roles[AuthorRole] = "author"; roles[ServerIdRole] = "appid"; roles[CategoryNameRole] = "category"; roles[CreatedTimeRole] = "createdtime"; roles[StateRole] = "state"; roles[StateTextRole] = "statetext"; roles[ProgressRole] = "progress"; return roles; } QString ServerAppModel::id(int i) const { return data(index(i), IdRole).toString(); } QString ServerAppModel::name(int i) const { return data(index(i), NameRole).toString(); } QString ServerAppModel::stateText(int i) const { return data(index(i), StateTextRole).toString(); } int ServerAppModel::launch(const QString& application) { int result = -1; HMI_DEBUG("launch", "ApplicationLauncher launch %s.", application.toStdString().c_str()); result = afm_user_daemon_proxy->start(application).value().toInt(); HMI_DEBUG("launch", "ApplicationLauncher pid: %d.", result); return result; } void ServerAppModel::appChanged(const QString& info) { QJsonDocument japps = QJsonDocument::fromJson(info.toUtf8()); QJsonObject const& jso = japps.object(); QString operation = jso["operation"].toString(); QString id = jso["data"].toString(); if (operation == "uninstall") { for (int i = 0; i < applist.size(); ++i) { if (applist.at(i).id() == id) { setData(index(i), AppInfo::Install, StateRole); break; } } } } void ServerAppModel::install(int i) { setData(index(i), AppInfo::Downloading, StateRole); QString url = getWgtUrl(applist[i].wgtPath()); HttpClient client(url); client.download( getDownloadFilePath(applist[i].fileName()), [this, i](const QString&) { setData(index(i), AppInfo::Installing, StateRole); QTimer::singleShot(3000, this, [this, i] { QString installResult = afm_user_daemon_proxy->install( getDownloadFilePath(applist[i].fileName())); setData(index(i), installResult.isEmpty() ? AppInfo::Install : AppInfo::Launch, StateRole); setData(index(i), 0.0, ProgressRole); }); }, [this, i](const QString& error) { HMI_ERROR("ERROR", "%s", error.toStdString().c_str()); setData(index(i), AppInfo::Install, StateRole); setData(index(i), 0.0, ProgressRole); }, [this, i](const qint64 bytesReceived, const qint64 bytesTotal) { qreal progressValue = ((qreal)bytesReceived / bytesTotal) * 100; setData(index(i), progressValue, ProgressRole); }); } void ServerAppModel::clearList() { beginResetModel(); applist.clear(); endResetModel(); } void ServerAppModel::getPrevPage(int PageIndex, QString name, int type) { this->getAppPage(PageIndex > 0 ? PageIndex - 1 : 0, PAGE_SIZE, name, type, true); } void ServerAppModel::getNextPage(int PageIndex, QString name, int type) { this->getAppPage(applist.count() >= PAGE_SIZE ? PageIndex + 1 : PageIndex, PAGE_SIZE, name, type); } void ServerAppModel::setNativeApplist(const QList& applist) { nativeApplist.clear(); nativeApplist = applist; checkAppState(); } void ServerAppModel::checkAppState() { if (applist.isEmpty() || nativeApplist.isEmpty()) { return; } QList::iterator it; int idx = 0; for (it = applist.begin(); it != applist.end(); ++it) { QList::iterator nit; for (nit = nativeApplist.begin(); nit != nativeApplist.end(); ++nit) { if ((*it).id() == (*nit).id()) { setData(index(idx), (*it).version() != (*nit).version() ? AppInfo::Update : AppInfo::Launch, StateRole); break; } } idx++; } } void ServerAppModel::getAppPage(int pageIndex, int pageSize, QString name, int type, bool isPrev) { QString url = getUrlWithPage(SERVER_API_LIST, pageIndex * pageSize, pageSize) .append(QString("&appDeviceTypeId=%1").arg(QString::number(0))); if (!name.isEmpty()) { // get search list by name url.append(QString("&keyWord=%1").arg(name)); } if (type != -1) { // get search list by type url.append(QString("&appTypeId=%1").arg(QString::number(type))); } HMI_ERROR("Message", "%s", url.toStdString().c_str()); HttpClient client(url); client.get( [=](const QString& result) { QJsonDocument jresult = QJsonDocument::fromJson(result.toUtf8()); QJsonObject const& jro = jresult.object(); QJsonArray const& jappList = jro["pagination_data"].toArray(); int offsetSize = 0; bool distinct = true; beginResetModel(); if (isPrev || applist.size() < PAGE_SIZE || jappList.size() == PAGE_SIZE) { applist.clear(); distinct = false; } else { //offsetSize = 0; if (applist.size() > PAGE_SIZE) { for (int i = 0; i < (applist.size() - PAGE_SIZE); i++) { applist.removeLast(); offsetSize--; } } } for (auto const& app : jappList) { QJsonObject const& jso = app.toObject(); AppInfo appinfo; appinfo.readFromServer(jso); if (distinct) { if (applist.contains(appinfo)) { continue; } else { offsetSize++; } } applist.append(appinfo); } endResetModel(); checkAppState(); emit requestCompleted(offsetSize, pageIndex, PAGE_SIZE, isPrev); }, [=](const QString& msg) { HMI_ERROR("response", "response error: %s", msg.toStdString().c_str()); }); }