/* * This file is part of Remote Support Desktop * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp * Copyright 2020, 2021 Daniel Teichmann * Copyright 2020, 2021 Mike Gabriel * SPDX-License-Identifier: GPL-2.0-or-later * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "main_qmladaptor.h" MainQMLAdaptor::MainQMLAdaptor(QObject *parent, QQmlApplicationEngine* engine, DBusAPI *dbus_api) : QObject(parent) { Q_ASSERT(engine != nullptr); Q_ASSERT(dbus_api != nullptr); _engine = engine; _dbus_api = dbus_api; _selected_rwa_host = nullptr; _rwaHostModel = new QList; QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, _dbus_api, QOverload<>::of(&DBusAPI::get_web_app_hosts_request)); timer->start(10000); qmlRegisterUncreatableMetaObject( Toast::staticMetaObject, // meta object created by Q_NAMESPACE macro "rwa.toast.type", // import statement (can be any string) 1, 0, // major and minor version of the import "ToastType", // name in QML (does not have to match C++ name) "Error: only enums" // error if someone tries to create a ToastType object ); } void MainQMLAdaptor::onRwaHostSelected(QString host_uuid) { Q_ASSERT(host_uuid != ""); RWAHost *_host = nullptr; for (int i = 0; i < getRWAHostModel().size(); i++) { QObject *obj = _rwaHostModel->value(i); RWAHost *host = qobject_cast(obj); Q_ASSERT(host != nullptr); if (host->uuid() == host_uuid) { _host = host; } } Q_ASSERT(_host != nullptr); _selected_rwa_host = _host; qDebug() << "RWAHost was selected!" << _selected_rwa_host->uuid() << "aka" << _selected_rwa_host->alias(); setRWAHostSelected(true); } RWAHost* MainQMLAdaptor::getSelectedRWAHost() { return _selected_rwa_host; } void MainQMLAdaptor::setRWAHostModel(QList *rwa_hosts) { _rwaHostModel = rwa_hosts; emit rwaHostModelChanged(*rwa_hosts); } void MainQMLAdaptor::addRWAHost(RWAHost *rwa_host) { _rwaHostModel->append(rwa_host); emit rwaHostModelChanged(*_rwaHostModel); } void MainQMLAdaptor::removeRWAHost(RWAHost *rwa_host) { _rwaHostModel->removeOne(rwa_host); emit rwaHostModelChanged(*_rwaHostModel); } QList MainQMLAdaptor::getRWAHostModel() { return *_rwaHostModel; } void MainQMLAdaptor::setRWAHostSelected(bool value) { // Find item via 'objectName' QObject *sidebar_drawer = _engine->rootObjects().takeFirst()-> findChild("sidebar_drawer"); if (sidebar_drawer) { sidebar_drawer->setProperty("rwaHostIsSelected", value); } else { qWarning() << "Unable to find 'sidebar_drawer' Item!"; } QObject *server_chooser = _engine->rootObjects().takeFirst()-> findChild("server_chooser"); if (server_chooser) { server_chooser->setProperty("displayText", value ? server_chooser->property("currentText") : tr("No RWA host available!")); server_chooser->setProperty("enabled", value); } else { qWarning() << "Unable to find 'server_chooser' Item!"; } } void MainQMLAdaptor::get_web_app_hosts_response(QJsonDocument *doc) { // Q_ASSERT lets the program crash immediatly at startup, // when the session service is not started. // Don't use Q_ASSERT(doc != nullptr); instead use: if (doc == nullptr) { setRWAHostSelected(false); showToast(tr("Can't connect to underlying session service!"), 9800, Toast::ToastError); // Go to the first page on the stack. main_content_pop(nullptr); return; } bool atLeastOneHostAvailable = false; // Get the QJsonObject QJsonObject jObject = doc->object(); QVariantMap mainMap = jObject.toVariantMap(); // Status of request QString request_status = mainMap["status"].toString(); if (request_status == "success") { // Building host_objects QJsonArray host_objects = jObject.value("hosts").toArray(); QList *all_rwa_hosts = new QList; foreach (const QJsonValue &host_object, host_objects) { QString host_uuid = host_object["uuid"].toString(); QString host_alias = host_object["alias"].toString(); QString host_url = host_object["url"].toString(); if (host_url == "" || host_uuid == "") { // This two values are required and can't be omitted. QString reason = tr("A host object in the response of D-Bus service lacks" " a necessary value. (host_url or host_uuid)"); qCritical().noquote() << tr("An error occured while adding a new host:") << reason; return; } if (host_alias == "") { qDebug().noquote() << QString("An alias for the host wasn't delivered " "so just use '%0' as alias.").arg(host_url); host_alias = host_url; } // Now built RWAHost object. RWAHost *rwa_host = new RWAHost(host_uuid, host_alias, host_url); all_rwa_hosts->append(rwa_host); bool found = false; for (int i = 0; i < this->_rwaHostModel->size(); i++) { RWAHost* old_host = qobject_cast(_rwaHostModel->value(i)); Q_ASSERT(old_host != nullptr); if (rwa_host->uuid() == old_host->uuid()) { found = true; break; } } atLeastOneHostAvailable = true; if (!found) { qInfo().noquote() << QString(tr("Successfully added new RWAHost '%0'")) .arg(rwa_host->alias()); addRWAHost(rwa_host); } } for (int i = 0; i < this->_rwaHostModel->size(); i++) { RWAHost* old_host = qobject_cast(_rwaHostModel->value(i)); Q_ASSERT(old_host != nullptr); bool found = false; for (RWAHost *host : *all_rwa_hosts) { if (host->uuid() == old_host->uuid()) { found = true; break; } } if (!found) { removeRWAHost(old_host); qInfo().noquote() << QString(tr("Removed RWAHost '%0'")).arg(old_host->alias()); } } } else { QString reason = tr("An error occured while adding a new host:"); qCritical().noquote() << reason; QString type = mainMap["type"].toString(); if (type != "") { reason = QString(tr("The error is not clear. The session service " "responded with status type '%0'")).arg(type); qCritical().noquote() << reason; } else { reason = QString(tr("The error is not clear. The session service " "responded with no status type!")); qCritical().noquote() << reason; } return; } if (!atLeastOneHostAvailable) { main_content_replace("scenes/Scene_no_server_available.qml"); } setRWAHostSelected(atLeastOneHostAvailable); } void MainQMLAdaptor::main_content_push(QString scene) { // Find item via 'objectName' QObject *window = _engine->rootObjects().takeFirst(); Q_ASSERT(window != nullptr); QObject *main_content = _engine->rootObjects().takeFirst()->findChild("main_content"); Q_ASSERT(main_content != nullptr); QVariant to_cast = main_content->property("currentItem"); QObject *obj = qvariant_cast(to_cast); if (obj) { if (!(scene.contains(obj->objectName()))) { QVariant arg = QVariant::fromValue(scene); if(!QMetaObject::invokeMethod(window, "main_content_push", Q_ARG(QVariant, arg))) qDebug() << "Failed to invoke push"; } } } void MainQMLAdaptor::main_content_pop(QString scene) { // Find item via 'objectName' QObject *window = _engine->rootObjects().takeFirst(); Q_ASSERT(window != nullptr); QObject *main_content = _engine->rootObjects().takeFirst()-> findChild("main_content"); Q_ASSERT(main_content != nullptr); QVariant to_cast = main_content->property("currentItem"); QObject *obj = qvariant_cast(to_cast); if (obj) { if (!(scene.contains(obj->objectName()))) { QVariant arg = QVariant::fromValue(scene); if(!QMetaObject::invokeMethod(window, "main_content_pop", Q_ARG(QVariant, arg))) qDebug() << "Failed to invoke pop"; } } } void MainQMLAdaptor::main_content_replace(QString scene) { // Find item via 'objectName' QObject *window = _engine->rootObjects().takeFirst(); Q_ASSERT(window != nullptr); QObject *main_content = _engine->rootObjects().takeFirst()-> findChild("main_content"); Q_ASSERT(main_content != nullptr); QVariant to_cast = main_content->property("currentItem"); QObject *obj = qvariant_cast(to_cast); if (obj) { QString scene_add_rwahost_wizard = "Scene_step_1"; if (!(scene.contains(obj->objectName()) || scene_add_rwahost_wizard.contains(obj->objectName()))) { QVariant arg = QVariant::fromValue(scene); if (!QMetaObject::invokeMethod(window, "main_content_replace", Q_ARG(QVariant, arg))) { qDebug() << "Failed to invoke replace"; } } } } bool MainQMLAdaptor::openMessageDialog(QString title, QString text, QMessageBox::Icon icon) { _messageDialogText = text; _messageDialogTitle = title; _messageDialogIcon = icon; _showMessageDialog = true; emit messageDialogIconChanged(_messageDialogIcon); emit messageDialogTitleChanged(_messageDialogTitle); emit messageDialogTextChanged(_messageDialogText); emit showMessageDialogChanged(_showMessageDialog); qDebug() << "Opening MessageDialog!"; return true; } QString MainQMLAdaptor::getMessageDialogTitle() { return _messageDialogTitle; } QString MainQMLAdaptor::getMessageDialogText() { return _messageDialogText; } QMessageBox::Icon MainQMLAdaptor::getMessageDialogIcon() { return _messageDialogIcon; } bool MainQMLAdaptor::getShowMessageDialog() { return _showMessageDialog; } void MainQMLAdaptor::onCloseHandler() { // Do cleanup things here... emit onCloseSignal(); } void MainQMLAdaptor::showToast(QString text, uint durationMs, uint type) { // type is actually Toast::ToastType emit showToastSignal(text, QString::number(durationMs), type); }