Merge PR #190: System controller
This commit is contained in:
commit
80e3559578
@ -284,7 +284,6 @@ void NymeaConfiguration::getConfigurationsResponse(const QVariantMap ¶ms)
|
||||
webServerConfigurations()->clear();
|
||||
foreach (const QVariant &webServerVariant, params.value("params").toMap().value("webServerConfigurations").toList()) {
|
||||
QVariantMap webServerConfigMap = webServerVariant.toMap();
|
||||
qDebug() << "**********+ web config" << webServerConfigMap;
|
||||
WebServerConfiguration* config = new WebServerConfiguration(webServerConfigMap.value("id").toString(), QHostAddress(webServerConfigMap.value("address").toString()), webServerConfigMap.value("port").toInt(), webServerConfigMap.value("authenticationEnabled").toBool(), webServerConfigMap.value("sslEnabled").toBool());
|
||||
config->setPublicFolder(webServerConfigMap.value("publicFolder").toString());
|
||||
m_webServerConfigurations->addConfiguration(config);
|
||||
@ -293,7 +292,7 @@ void NymeaConfiguration::getConfigurationsResponse(const QVariantMap ¶ms)
|
||||
|
||||
void NymeaConfiguration::getAvailableLanguagesResponse(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "available languages" << params;
|
||||
// qDebug() << "available languages" << params;
|
||||
m_availableLanguages = params.value("params").toMap().value("languages").toStringList();
|
||||
emit availableLanguagesChanged();
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ void ZeroconfDiscovery::serviceEntryAdded(const QZeroConfService &entry)
|
||||
if (!host) {
|
||||
host = new NymeaHost(m_nymeaHosts);
|
||||
host->setUuid(uuid);
|
||||
qDebug() << "ZeroConf: Adding new host:" << serverName << uuid;
|
||||
// qDebug() << "ZeroConf: Adding new host:" << serverName << uuid;
|
||||
m_nymeaHosts->addHost(host);
|
||||
}
|
||||
host->setName(serverName);
|
||||
@ -124,13 +124,13 @@ void ZeroconfDiscovery::serviceEntryAdded(const QZeroConfService &entry)
|
||||
url.setPort(entry.port());
|
||||
Connection *connection = host->connections()->find(url);
|
||||
if (!connection) {
|
||||
qDebug() << "Zeroconf: Adding new connection to host:" << host->name() << url.toString();
|
||||
// qDebug() << "Zeroconf: Adding new connection to host:" << host->name() << url.toString();
|
||||
QString displayName = QString("%1:%2").arg(url.host()).arg(url.port());
|
||||
connection = new Connection(url, Connection::BearerTypeLan, sslEnabled, displayName);
|
||||
connection->setOnline(true);
|
||||
host->connections()->addConnection(connection);
|
||||
} else {
|
||||
qDebug() << "Zeroconf: Setting connection online:" << host->name() << url.toString();
|
||||
// qDebug() << "Zeroconf: Setting connection online:" << host->name() << url.toString();
|
||||
connection->setOnline(true);
|
||||
}
|
||||
}
|
||||
@ -183,7 +183,7 @@ void ZeroconfDiscovery::serviceEntryRemoved(const QZeroConfService &entry)
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Zeroconf: Setting connection offline:" << host->name() << url.toString();
|
||||
// qDebug() << "Zeroconf: Setting connection offline:" << host->name() << url.toString();
|
||||
connection->setOnline(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include "tagsmanager.h"
|
||||
#include "configuration/nymeaconfiguration.h"
|
||||
#include "connection/awsclient.h"
|
||||
#include "system/systemcontroller.h"
|
||||
|
||||
#include "connection/tcpsockettransport.h"
|
||||
#include "connection/websockettransport.h"
|
||||
@ -39,7 +40,8 @@ Engine::Engine(QObject *parent) :
|
||||
m_ruleManager(new RuleManager(m_jsonRpcClient, this)),
|
||||
m_logManager(new LogManager(m_jsonRpcClient, this)),
|
||||
m_tagsManager(new TagsManager(m_jsonRpcClient, this)),
|
||||
m_nymeaConfiguration(new NymeaConfiguration(m_jsonRpcClient, this))
|
||||
m_nymeaConfiguration(new NymeaConfiguration(m_jsonRpcClient, this)),
|
||||
m_systemController(new SystemController(m_jsonRpcClient, this))
|
||||
{
|
||||
m_connection->registerTransport(new TcpSocketTransportFactory());
|
||||
m_connection->registerTransport(new WebsocketTransportFactory());
|
||||
@ -97,6 +99,11 @@ NymeaConfiguration *Engine::nymeaConfiguration() const
|
||||
return m_nymeaConfiguration;
|
||||
}
|
||||
|
||||
SystemController *Engine::systemController() const
|
||||
{
|
||||
return m_systemController;
|
||||
}
|
||||
|
||||
void Engine::deployCertificate()
|
||||
{
|
||||
if (!m_jsonRpcClient->connected()) {
|
||||
@ -129,6 +136,7 @@ void Engine::onConnectedChanged()
|
||||
m_deviceManager->init();
|
||||
m_ruleManager->init();
|
||||
m_nymeaConfiguration->init();
|
||||
m_systemController->init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ class RuleManager;
|
||||
class LogManager;
|
||||
class TagsManager;
|
||||
class NymeaConfiguration;
|
||||
class SystemController;
|
||||
|
||||
class Engine : public QObject
|
||||
{
|
||||
@ -42,6 +43,7 @@ class Engine : public QObject
|
||||
Q_PROPERTY(TagsManager* tagsManager READ tagsManager CONSTANT)
|
||||
Q_PROPERTY(JsonRpcClient* jsonRpcClient READ jsonRpcClient CONSTANT)
|
||||
Q_PROPERTY(NymeaConfiguration* nymeaConfiguration READ nymeaConfiguration CONSTANT)
|
||||
Q_PROPERTY(SystemController* systemController READ systemController CONSTANT)
|
||||
|
||||
public:
|
||||
explicit Engine(QObject *parent = nullptr);
|
||||
@ -56,6 +58,7 @@ public:
|
||||
JsonRpcClient *jsonRpcClient() const;
|
||||
LogManager *logManager() const;
|
||||
NymeaConfiguration *nymeaConfiguration() const;
|
||||
SystemController *systemController() const;
|
||||
|
||||
Q_INVOKABLE void deployCertificate();
|
||||
|
||||
@ -67,6 +70,7 @@ private:
|
||||
LogManager *m_logManager;
|
||||
TagsManager *m_tagsManager;
|
||||
NymeaConfiguration *m_nymeaConfiguration;
|
||||
SystemController *m_systemController;
|
||||
|
||||
private slots:
|
||||
void onConnectedChanged();
|
||||
|
||||
@ -133,7 +133,7 @@ void JsonRpcClient::notificationReceived(const QVariantMap &data)
|
||||
|
||||
void JsonRpcClient::isCloudConnectedReply(const QVariantMap &data)
|
||||
{
|
||||
qDebug() << "Cloud is connected" << data;
|
||||
// qDebug() << "Cloud is connected" << data;
|
||||
QMetaEnum connectionStateEnum = QMetaEnum::fromType<CloudConnectionState>();
|
||||
m_cloudConnectionState = static_cast<CloudConnectionState>(connectionStateEnum.keyToValue(data.value("params").toMap().value("connectionState").toByteArray().data()));
|
||||
emit cloudConnectionStateChanged();
|
||||
|
||||
@ -56,6 +56,12 @@
|
||||
#include "ruletemplates/ruleactionparamtemplate.h"
|
||||
#include "connection/awsclient.h"
|
||||
#include "models/devicemodel.h"
|
||||
#include "system/systemcontroller.h"
|
||||
#include "types/package.h"
|
||||
#include "types/packages.h"
|
||||
#include "types/repository.h"
|
||||
#include "types/repositories.h"
|
||||
#include "models/packagesfiltermodel.h"
|
||||
|
||||
#include <QtQml/qqml.h>
|
||||
|
||||
@ -199,6 +205,13 @@ void registerQmlTypes() {
|
||||
qmlRegisterUncreatableType<RuleActionTemplate>(uri, 1, 0, "RuleActionTemplate", "Get it from RuleActionTemplates");
|
||||
qmlRegisterUncreatableType<RuleActionParamTemplates>(uri, 1, 0, "RuleActionParamTemplates", "Get it from RuleActionTemplate");
|
||||
qmlRegisterUncreatableType<RuleActionParamTemplate>(uri, 1, 0, "RuleActionParamTemplate", "Get it from RuleActionParamTemplates");
|
||||
|
||||
qmlRegisterUncreatableType<SystemController>(uri, 1, 0, "SystemController", "Get it from Engine");
|
||||
qmlRegisterUncreatableType<Packages>(uri, 1, 0, "Packages", "Get it from SystemController");
|
||||
qmlRegisterUncreatableType<Package>(uri, 1, 0, "Package", "Get it from Packages");
|
||||
qmlRegisterUncreatableType<Repositories>(uri, 1, 0, "Repositories", "Get it from SystemController");
|
||||
qmlRegisterUncreatableType<Repository>(uri, 1, 0, "Repository", "Get it from Repositories");
|
||||
qmlRegisterType<PackagesFilterModel>(uri, 1, 0, "PackagesFilterModel");
|
||||
}
|
||||
|
||||
#endif // LIBNYMEAAPPCORE_H
|
||||
|
||||
@ -46,6 +46,7 @@ SOURCES += \
|
||||
deviceclasses.cpp \
|
||||
deviceclassesproxy.cpp \
|
||||
devicediscovery.cpp \
|
||||
models/packagesfiltermodel.cpp \
|
||||
vendorsproxy.cpp \
|
||||
pluginsproxy.cpp \
|
||||
interfacesmodel.cpp \
|
||||
@ -81,7 +82,8 @@ SOURCES += \
|
||||
configuration/nymeaconfiguration.cpp \
|
||||
configuration/mqttpolicy.cpp \
|
||||
configuration/mqttpolicies.cpp \
|
||||
models/devicemodel.cpp
|
||||
models/devicemodel.cpp \
|
||||
system/systemcontroller.cpp
|
||||
|
||||
HEADERS += \
|
||||
engine.h \
|
||||
@ -107,6 +109,7 @@ HEADERS += \
|
||||
deviceclasses.h \
|
||||
deviceclassesproxy.h \
|
||||
devicediscovery.h \
|
||||
models/packagesfiltermodel.h \
|
||||
vendorsproxy.h \
|
||||
pluginsproxy.h \
|
||||
interfacesmodel.h \
|
||||
@ -142,4 +145,10 @@ HEADERS += \
|
||||
configuration/nymeaconfiguration.h \
|
||||
configuration/mqttpolicy.h \
|
||||
configuration/mqttpolicies.h \
|
||||
models/devicemodel.h
|
||||
models/devicemodel.h \
|
||||
system/systemcontroller.h
|
||||
|
||||
unix {
|
||||
target.path = /usr/lib
|
||||
INSTALLS += target
|
||||
}
|
||||
|
||||
55
libnymea-app-core/models/packagesfiltermodel.cpp
Normal file
55
libnymea-app-core/models/packagesfiltermodel.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "packagesfiltermodel.h"
|
||||
#include "types/package.h"
|
||||
|
||||
PackagesFilterModel::PackagesFilterModel(QObject *parent): QSortFilterProxyModel(parent)
|
||||
{
|
||||
setSortRole(Packages::RoleDisplayName);
|
||||
sort(0);
|
||||
}
|
||||
|
||||
Packages *PackagesFilterModel::packages() const
|
||||
{
|
||||
return m_packages;
|
||||
}
|
||||
|
||||
void PackagesFilterModel::setPackages(Packages *packages)
|
||||
{
|
||||
if (m_packages != packages) {
|
||||
m_packages = packages;
|
||||
setSourceModel(packages);
|
||||
connect(packages, &Packages::countChanged, this, &PackagesFilterModel::countChanged);
|
||||
emit packagesChanged();
|
||||
emit countChanged();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
bool PackagesFilterModel::updatesOnly() const
|
||||
{
|
||||
return m_updatesOnly;
|
||||
}
|
||||
|
||||
void PackagesFilterModel::setUpdatesOnly(bool updatesOnly)
|
||||
{
|
||||
if (m_updatesOnly != updatesOnly) {
|
||||
m_updatesOnly = updatesOnly;
|
||||
emit updatesOnlyChanged();
|
||||
invalidateFilter();
|
||||
emit countChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Package *PackagesFilterModel::get(int index) const
|
||||
{
|
||||
return m_packages->get(mapToSource(this->index(index, 0)).row());
|
||||
}
|
||||
|
||||
bool PackagesFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
if (m_updatesOnly) {
|
||||
if (!m_packages->get(source_row)->updateAvailable()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
39
libnymea-app-core/models/packagesfiltermodel.h
Normal file
39
libnymea-app-core/models/packagesfiltermodel.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef PACKAGESFILTERMODEL_H
|
||||
#define PACKAGESFILTERMODEL_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include "types/packages.h"
|
||||
|
||||
class PackagesFilterModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(Packages* packages READ packages WRITE setPackages NOTIFY packagesChanged)
|
||||
Q_PROPERTY(bool updatesOnly READ updatesOnly WRITE setUpdatesOnly NOTIFY updatesOnlyChanged)
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||
|
||||
public:
|
||||
explicit PackagesFilterModel(QObject *parent = nullptr);
|
||||
|
||||
Packages* packages() const;
|
||||
void setPackages(Packages *packages);
|
||||
|
||||
bool updatesOnly() const;
|
||||
void setUpdatesOnly(bool updatesOnly);
|
||||
|
||||
Q_INVOKABLE Package* get(int index) const;
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
void packagesChanged();
|
||||
void updatesOnlyChanged();
|
||||
|
||||
private:
|
||||
Packages *m_packages;
|
||||
|
||||
bool m_updatesOnly = false;
|
||||
};
|
||||
|
||||
#endif // PACKAGESFILTERMODEL_H
|
||||
205
libnymea-app-core/system/systemcontroller.cpp
Normal file
205
libnymea-app-core/system/systemcontroller.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
#include "systemcontroller.h"
|
||||
|
||||
#include "types/package.h"
|
||||
#include "types/repository.h"
|
||||
#include "types/packages.h"
|
||||
#include "types/repositories.h"
|
||||
|
||||
SystemController::SystemController(JsonRpcClient *jsonRpcClient, QObject *parent):
|
||||
JsonHandler(parent),
|
||||
m_jsonRpcClient(jsonRpcClient)
|
||||
{
|
||||
m_jsonRpcClient->registerNotificationHandler(this, "notificationReceived");
|
||||
m_packages = new Packages(this);
|
||||
m_repositories = new Repositories(this);
|
||||
}
|
||||
|
||||
void SystemController::init()
|
||||
{
|
||||
m_packages->clear();
|
||||
m_repositories->clear();
|
||||
if (m_jsonRpcClient->ensureServerVersion("2.0")) {
|
||||
m_jsonRpcClient->sendCommand("System.GetCapabilities", this, "getCapabilitiesResponse");
|
||||
} else {
|
||||
m_powerManagementAvailable = false;
|
||||
}
|
||||
}
|
||||
|
||||
QString SystemController::nameSpace() const
|
||||
{
|
||||
return "System";
|
||||
}
|
||||
|
||||
bool SystemController::powerManagementAvailable() const
|
||||
{
|
||||
return m_powerManagementAvailable;
|
||||
}
|
||||
|
||||
bool SystemController::updateManagementAvailable() const
|
||||
{
|
||||
return m_updateManagementAvailable;
|
||||
}
|
||||
|
||||
void SystemController::reboot()
|
||||
{
|
||||
m_jsonRpcClient->sendCommand("System.Reboot");
|
||||
}
|
||||
|
||||
void SystemController::shutdown()
|
||||
{
|
||||
m_jsonRpcClient->sendCommand("System.Shutdown");
|
||||
}
|
||||
|
||||
bool SystemController::updateRunning() const
|
||||
{
|
||||
return m_updateRunning;
|
||||
}
|
||||
|
||||
Packages *SystemController::packages() const
|
||||
{
|
||||
return m_packages;
|
||||
}
|
||||
|
||||
void SystemController::updatePackages(const QString packageId)
|
||||
{
|
||||
QVariantMap params;
|
||||
if (!packageId.isEmpty()) {
|
||||
params.insert("packageIds", QStringList() << packageId);
|
||||
}
|
||||
m_jsonRpcClient->sendCommand("System.UpdatePackages", params);
|
||||
}
|
||||
|
||||
void SystemController::removePackages(const QString packageId)
|
||||
{
|
||||
QVariantMap params;
|
||||
if (!packageId.isEmpty()) {
|
||||
params.insert("packageIds", QStringList() << packageId);
|
||||
}
|
||||
m_jsonRpcClient->sendCommand("System.RemovePackages", params, this, "removePackageResponse");
|
||||
}
|
||||
|
||||
Repositories *SystemController::repositories() const
|
||||
{
|
||||
return m_repositories;
|
||||
}
|
||||
|
||||
void SystemController::enableRepository(const QString &id, bool enabled)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("repositoryId", id);
|
||||
params.insert("enabled", enabled);
|
||||
m_jsonRpcClient->sendCommand("System.EnableRepository", params);
|
||||
}
|
||||
|
||||
void SystemController::getCapabilitiesResponse(const QVariantMap &data)
|
||||
{
|
||||
qDebug() << "capabilities received" << data;
|
||||
m_powerManagementAvailable = data.value("params").toMap().value("powerManagement").toBool();
|
||||
emit powerManagementAvailableChanged();
|
||||
|
||||
m_updateManagementAvailable = data.value("params").toMap().value("updateManagement").toBool();
|
||||
emit updateManagementAvailableChanged();
|
||||
|
||||
if (m_updateManagementAvailable) {
|
||||
m_jsonRpcClient->sendCommand("System.GetUpdateStatus", this, "getUpdateStatusResponse");
|
||||
m_jsonRpcClient->sendCommand("System.GetPackages", this, "getPackagesResponse");
|
||||
m_jsonRpcClient->sendCommand("System.GetRepositories", this, "getRepositoriesResponse");
|
||||
}
|
||||
}
|
||||
|
||||
void SystemController::getUpdateStatusResponse(const QVariantMap &data)
|
||||
{
|
||||
m_updateRunning = data.value("params").toMap().value("updateRunning").toBool();
|
||||
emit updateRunningChanged();
|
||||
}
|
||||
|
||||
void SystemController::getPackagesResponse(const QVariantMap &data)
|
||||
{
|
||||
foreach (const QVariant &packageVariant, data.value("params").toMap().value("packages").toList()) {
|
||||
QString id = packageVariant.toMap().value("id").toString();
|
||||
QString displayName = packageVariant.toMap().value("displayName").toString();
|
||||
Package *p = new Package(id, displayName);
|
||||
p->setInstalledVersion(packageVariant.toMap().value("installedVersion").toString());
|
||||
p->setCandidateVersion(packageVariant.toMap().value("candidateVersion").toString());
|
||||
p->setChangelog(packageVariant.toMap().value("changelog").toString());
|
||||
p->setUpdateAvailable(packageVariant.toMap().value("updateAvailable").toBool());
|
||||
p->setRollbackAvailable(packageVariant.toMap().value("rollbackAvailable").toBool());
|
||||
p->setCanRemove(packageVariant.toMap().value("canRemove").toBool());
|
||||
m_packages->addPackage(p);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemController::getRepositoriesResponse(const QVariantMap &data)
|
||||
{
|
||||
qDebug() << "******** Repos" << data;
|
||||
foreach (const QVariant &repoVariant, data.value("params").toMap().value("repositories").toList()) {
|
||||
QString id = repoVariant.toMap().value("id").toString();
|
||||
QString displayName = repoVariant.toMap().value("displayName").toString();
|
||||
Repository *repo = new Repository(id, displayName);
|
||||
repo->setEnabled(repoVariant.toMap().value("enabled").toBool());
|
||||
m_repositories->addRepository(repo);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemController::removePackageResponse(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Remove result" << params;
|
||||
}
|
||||
|
||||
void SystemController::notificationReceived(const QVariantMap &data)
|
||||
{
|
||||
qDebug() << "System Notification" << data.value("notification");
|
||||
QString notification = data.value("notification").toString();
|
||||
if (notification == "System.UpdateStatusChanged") {
|
||||
m_updateRunning = data.value("params").toMap().value("updateRunning").toBool();
|
||||
emit updateRunningChanged();
|
||||
} else if (notification == "System.PackageAdded") {
|
||||
QVariantMap packageMap = data.value("params").toMap().value("package").toMap();
|
||||
QString id = packageMap.value("id").toString();
|
||||
QString displayName = packageMap.value("displayName").toString();
|
||||
Package *p = new Package(id, displayName);
|
||||
p->setInstalledVersion(packageMap.value("installedVersion").toString());
|
||||
p->setCandidateVersion(packageMap.value("candidateVersion").toString());
|
||||
p->setChangelog(packageMap.value("changelog").toString());
|
||||
p->setUpdateAvailable(packageMap.value("updateAvailable").toBool());
|
||||
p->setRollbackAvailable(packageMap.value("rollbackAvailable").toBool());
|
||||
p->setCanRemove(packageMap.value("canRemove").toBool());
|
||||
m_packages->addPackage(p);
|
||||
} else if (notification == "System.PackageChanged") {
|
||||
QVariantMap packageMap = data.value("params").toMap().value("package").toMap();
|
||||
QString id = packageMap.value("id").toString();
|
||||
Package *p = m_packages->getPackage(id);
|
||||
if (!p) {
|
||||
qWarning() << "Received a package update notification for a package we don't know";
|
||||
return;
|
||||
}
|
||||
p->setInstalledVersion(packageMap.value("installedVersion").toString());
|
||||
p->setCandidateVersion(packageMap.value("candidateVersion").toString());
|
||||
p->setChangelog(packageMap.value("changelog").toString());
|
||||
p->setUpdateAvailable(packageMap.value("updateAvailable").toBool());
|
||||
p->setRollbackAvailable(packageMap.value("rollbackAvailable").toBool());
|
||||
p->setCanRemove(packageMap.value("canRemove").toBool());
|
||||
} else if (notification == "System.PackageRemoved") {
|
||||
QString packageId = data.value("params").toMap().value("packageId").toString();
|
||||
m_packages->removePackage(packageId);
|
||||
} else if (notification == "System.RepositoryAdded") {
|
||||
QVariantMap repoMap = data.value("params").toMap().value("repository").toMap();
|
||||
QString id = repoMap.value("id").toString();
|
||||
QString displayName = repoMap.value("displayName").toString();
|
||||
Repository *repo = new Repository(id, displayName);
|
||||
repo->setEnabled(repoMap.value("enabled").toBool());
|
||||
m_repositories->addRepository(repo);
|
||||
} else if (notification == "System.RepositoryChanged") {
|
||||
QVariantMap repoMap = data.value("params").toMap().value("repository").toMap();
|
||||
QString id = repoMap.value("id").toString();
|
||||
Repository *repo = m_repositories->getRepository(id);
|
||||
if (!repo) {
|
||||
qWarning() << "Received a repository update notification for a repository we don't know";
|
||||
return;
|
||||
}
|
||||
repo->setEnabled(repoMap.value("enabled").toBool());
|
||||
} else if (notification == "System.RepositoryRemoved") {
|
||||
QString repositoryId = data.value("params").toMap().value("repositoryId").toString();
|
||||
m_repositories->removeRepository(repositoryId);
|
||||
}
|
||||
}
|
||||
69
libnymea-app-core/system/systemcontroller.h
Normal file
69
libnymea-app-core/system/systemcontroller.h
Normal file
@ -0,0 +1,69 @@
|
||||
#ifndef SYSTEMCONTROLLER_H
|
||||
#define SYSTEMCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "jsonrpc/jsonrpcclient.h"
|
||||
|
||||
class Repositories;
|
||||
class Packages;
|
||||
|
||||
class SystemController : public JsonHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool powerManagementAvailable READ powerManagementAvailable NOTIFY powerManagementAvailableChanged)
|
||||
// Whether the update mechanism is available in the connected core
|
||||
Q_PROPERTY(bool updateManagementAvailable READ updateManagementAvailable NOTIFY updateManagementAvailableChanged)
|
||||
|
||||
Q_PROPERTY(bool updateRunning READ updateRunning NOTIFY updateRunningChanged)
|
||||
Q_PROPERTY(Packages* packages READ packages CONSTANT)
|
||||
Q_PROPERTY(Repositories* repositories READ repositories CONSTANT)
|
||||
|
||||
public:
|
||||
explicit SystemController(JsonRpcClient *jsonRpcClient, QObject *parent = nullptr);
|
||||
|
||||
void init();
|
||||
QString nameSpace() const override;
|
||||
|
||||
bool powerManagementAvailable() const;
|
||||
bool updateManagementAvailable() const;
|
||||
|
||||
Q_INVOKABLE void reboot();
|
||||
Q_INVOKABLE void shutdown();
|
||||
|
||||
bool updateRunning() const;
|
||||
|
||||
Packages* packages() const;
|
||||
Q_INVOKABLE void updatePackages(const QString packageId = QString());
|
||||
Q_INVOKABLE void removePackages(const QString packageId = QString());
|
||||
|
||||
Repositories* repositories() const;
|
||||
Q_INVOKABLE void enableRepository(const QString &id, bool enabled);
|
||||
|
||||
|
||||
signals:
|
||||
void powerManagementAvailableChanged();
|
||||
void updateManagementAvailableChanged();
|
||||
void updateRunningChanged();
|
||||
|
||||
private slots:
|
||||
void getCapabilitiesResponse(const QVariantMap &data);
|
||||
void getUpdateStatusResponse(const QVariantMap &data);
|
||||
void getPackagesResponse(const QVariantMap &data);
|
||||
void getRepositoriesResponse(const QVariantMap &data);
|
||||
void removePackageResponse(const QVariantMap ¶ms);
|
||||
|
||||
void notificationReceived(const QVariantMap &data);
|
||||
|
||||
private:
|
||||
JsonRpcClient *m_jsonRpcClient = nullptr;
|
||||
|
||||
bool m_powerManagementAvailable = false;
|
||||
bool m_updateManagementAvailable = false;
|
||||
|
||||
bool m_updateRunning = false;
|
||||
Packages *m_packages = nullptr;
|
||||
Repositories *m_repositories = nullptr;
|
||||
};
|
||||
|
||||
#endif // SYSTEMCONTROLLER_H
|
||||
@ -8,6 +8,10 @@ QT -= gui
|
||||
QT += network
|
||||
|
||||
HEADERS += \
|
||||
types/package.h \
|
||||
types/packages.h \
|
||||
types/repositories.h \
|
||||
types/repository.h \
|
||||
types/types.h \
|
||||
types/vendor.h \
|
||||
types/vendors.h \
|
||||
@ -54,6 +58,10 @@ HEADERS += \
|
||||
types/tags.h
|
||||
|
||||
SOURCES += \
|
||||
types/package.cpp \
|
||||
types/packages.cpp \
|
||||
types/repositories.cpp \
|
||||
types/repository.cpp \
|
||||
types/vendor.cpp \
|
||||
types/vendors.cpp \
|
||||
types/deviceclass.cpp \
|
||||
|
||||
97
libnymea-common/types/package.cpp
Normal file
97
libnymea-common/types/package.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
#include "package.h"
|
||||
|
||||
Package::Package(const QString &id, const QString &displayName, QObject *parent):
|
||||
QObject(parent),
|
||||
m_id(id),
|
||||
m_displayName(displayName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString Package::id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString Package::displayName() const
|
||||
{
|
||||
return m_displayName;
|
||||
}
|
||||
|
||||
QString Package::installedVersion() const
|
||||
{
|
||||
return m_installedVersion;
|
||||
}
|
||||
|
||||
void Package::setInstalledVersion(const QString &installedVersion)
|
||||
{
|
||||
if (m_installedVersion != installedVersion) {
|
||||
m_installedVersion = installedVersion;
|
||||
emit installedVersionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString Package::candidateVersion() const
|
||||
{
|
||||
return m_candidateVersion;
|
||||
}
|
||||
|
||||
void Package::setCandidateVersion(const QString &candidateVersion)
|
||||
{
|
||||
if (m_candidateVersion != candidateVersion) {
|
||||
m_candidateVersion = candidateVersion;
|
||||
emit candidateVersionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString Package::changelog() const
|
||||
{
|
||||
return m_changelog;
|
||||
}
|
||||
|
||||
void Package::setChangelog(const QString &changelog)
|
||||
{
|
||||
if (m_changelog != changelog) {
|
||||
m_changelog = changelog;
|
||||
emit changelogChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool Package::updateAvailable() const
|
||||
{
|
||||
return m_updateAvailable;
|
||||
}
|
||||
|
||||
void Package::setUpdateAvailable(bool updateAvailable)
|
||||
{
|
||||
if (m_updateAvailable != updateAvailable) {
|
||||
m_updateAvailable = updateAvailable;
|
||||
emit updateAvailableChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool Package::rollbackAvailable() const
|
||||
{
|
||||
return m_rollbackAvailable;
|
||||
}
|
||||
|
||||
void Package::setRollbackAvailable(bool rollbackAvailable)
|
||||
{
|
||||
if (m_rollbackAvailable != rollbackAvailable) {
|
||||
m_rollbackAvailable = rollbackAvailable;
|
||||
emit rollbackAvailableChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool Package::canRemove() const
|
||||
{
|
||||
return m_canRemove;
|
||||
}
|
||||
|
||||
void Package::setCanRemove(bool canRemove)
|
||||
{
|
||||
if (m_canRemove != canRemove) {
|
||||
m_canRemove = canRemove;
|
||||
emit canRemoveChanged();
|
||||
}
|
||||
}
|
||||
61
libnymea-common/types/package.h
Normal file
61
libnymea-common/types/package.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef PACKAGE_H
|
||||
#define PACKAGE_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Package : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString id READ id CONSTANT)
|
||||
Q_PROPERTY(QString displayName READ displayName CONSTANT)
|
||||
Q_PROPERTY(QString installedVersion READ installedVersion NOTIFY installedVersionChanged)
|
||||
Q_PROPERTY(QString candidateVersion READ candidateVersion NOTIFY candidateVersionChanged)
|
||||
Q_PROPERTY(QString changelog READ changelog NOTIFY changelogChanged)
|
||||
Q_PROPERTY(bool updateAvailable READ updateAvailable NOTIFY updateAvailableChanged)
|
||||
Q_PROPERTY(bool rollbackAvailable READ rollbackAvailable NOTIFY rollbackAvailableChanged)
|
||||
Q_PROPERTY(bool canRemove READ canRemove NOTIFY canRemoveChanged)
|
||||
|
||||
public:
|
||||
explicit Package(const QString &id, const QString &displayName, QObject *parent = nullptr);
|
||||
|
||||
QString id() const;
|
||||
QString displayName() const;
|
||||
|
||||
QString installedVersion() const;
|
||||
void setInstalledVersion(const QString &installedVersion);
|
||||
|
||||
QString candidateVersion() const;
|
||||
void setCandidateVersion(const QString &candidateVersion);
|
||||
|
||||
QString changelog() const;
|
||||
void setChangelog(const QString &changelog);
|
||||
|
||||
bool updateAvailable() const;
|
||||
void setUpdateAvailable(bool updateAvailable);
|
||||
|
||||
bool rollbackAvailable() const;
|
||||
void setRollbackAvailable(bool rollbackAvailable);
|
||||
|
||||
bool canRemove() const;
|
||||
void setCanRemove(bool canRemove);
|
||||
|
||||
signals:
|
||||
void installedVersionChanged();
|
||||
void candidateVersionChanged();
|
||||
void changelogChanged();
|
||||
void updateAvailableChanged();
|
||||
void rollbackAvailableChanged();
|
||||
void canRemoveChanged();
|
||||
|
||||
private:
|
||||
QString m_id;
|
||||
QString m_displayName;
|
||||
QString m_installedVersion;
|
||||
QString m_candidateVersion;
|
||||
QString m_changelog;
|
||||
bool m_updateAvailable = false;
|
||||
bool m_rollbackAvailable = false;
|
||||
bool m_canRemove = false;
|
||||
};
|
||||
|
||||
#endif // PACKAGE_H
|
||||
122
libnymea-common/types/packages.cpp
Normal file
122
libnymea-common/types/packages.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
#include "packages.h"
|
||||
#include "package.h"
|
||||
|
||||
Packages::Packages(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Packages::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_list.count();
|
||||
}
|
||||
|
||||
QVariant Packages::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
switch (role) {
|
||||
case RoleId:
|
||||
return m_list.at(index.row())->id();
|
||||
case RoleDisplayName:
|
||||
return m_list.at(index.row())->displayName();
|
||||
case RoleInstalledVersion:
|
||||
return m_list.at(index.row())->installedVersion();
|
||||
case RoleCandidateVersion:
|
||||
return m_list.at(index.row())->candidateVersion();
|
||||
case RoleChangelog:
|
||||
return m_list.at(index.row())->changelog();
|
||||
case RoleUpdateAvailable:
|
||||
return m_list.at(index.row())->updateAvailable();
|
||||
case RoleRollbackAvailable:
|
||||
return m_list.at(index.row())->rollbackAvailable();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> Packages::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(RoleId, "id");
|
||||
roles.insert(RoleDisplayName, "displayName");
|
||||
roles.insert(RoleInstalledVersion, "installedVersion");
|
||||
roles.insert(RoleCandidateVersion, "candidateVersion");
|
||||
roles.insert(RoleChangelog, "changelog");
|
||||
roles.insert(RoleUpdateAvailable, "updateAvailable");
|
||||
roles.insert(RoleRollbackAvailable, "rollbackAvailable");
|
||||
return roles;
|
||||
}
|
||||
|
||||
void Packages::addPackage(Package *package)
|
||||
{
|
||||
package->setParent(this);
|
||||
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||
m_list.append(package);
|
||||
connect(package, &Package::installedVersionChanged, this, [this, package](){
|
||||
emit dataChanged(index(m_list.indexOf(package)), index(m_list.indexOf(package)), {RoleInstalledVersion});
|
||||
emit countChanged();
|
||||
});
|
||||
connect(package, &Package::candidateVersionChanged, this, [this, package](){
|
||||
emit dataChanged(index(m_list.indexOf(package)), index(m_list.indexOf(package)), {RoleCandidateVersion});
|
||||
emit countChanged();
|
||||
});
|
||||
connect(package, &Package::changelogChanged, this, [this, package](){
|
||||
emit dataChanged(index(m_list.indexOf(package)), index(m_list.indexOf(package)), {RoleChangelog});
|
||||
emit countChanged();
|
||||
});
|
||||
connect(package, &Package::updateAvailableChanged, this, [this, package](){
|
||||
emit dataChanged(index(m_list.indexOf(package)), index(m_list.indexOf(package)), {RoleUpdateAvailable});
|
||||
emit countChanged();
|
||||
});
|
||||
connect(package, &Package::rollbackAvailableChanged, this, [this, package](){
|
||||
emit dataChanged(index(m_list.indexOf(package)), index(m_list.indexOf(package)), {RoleRollbackAvailable});
|
||||
emit countChanged();
|
||||
});
|
||||
endInsertRows();
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
void Packages::removePackage(const QString &packageId)
|
||||
{
|
||||
int idx = -1;
|
||||
for (int i = 0; i < m_list.count(); i++) {
|
||||
if (m_list.at(i)->id() == packageId) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginRemoveRows(QModelIndex(), idx, idx);
|
||||
m_list.takeAt(idx)->deleteLater();
|
||||
endRemoveRows();
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
Package *Packages::get(int index) const
|
||||
{
|
||||
if (index >= 0 && index < m_list.count()) {
|
||||
return m_list.at(index);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Package *Packages::getPackage(const QString &packageId)
|
||||
{
|
||||
foreach (Package *p, m_list) {
|
||||
if (p->id() == packageId) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Packages::clear()
|
||||
{
|
||||
beginResetModel();
|
||||
qDeleteAll(m_list);
|
||||
m_list.clear();
|
||||
endResetModel();
|
||||
emit countChanged();
|
||||
}
|
||||
45
libnymea-common/types/packages.h
Normal file
45
libnymea-common/types/packages.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef PACKAGES_H
|
||||
#define PACKAGES_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class Package;
|
||||
|
||||
class Packages: public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||
public:
|
||||
enum Roles {
|
||||
RoleId,
|
||||
RoleDisplayName,
|
||||
RoleInstalledVersion,
|
||||
RoleCandidateVersion,
|
||||
RoleChangelog,
|
||||
RoleUpdateAvailable,
|
||||
RoleRollbackAvailable
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit Packages(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
void addPackage(Package *package);
|
||||
void removePackage(const QString &packageId);
|
||||
|
||||
Q_INVOKABLE Package* get(int index) const;
|
||||
Q_INVOKABLE Package* getPackage(const QString &packageId);
|
||||
|
||||
void clear();
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
QList<Package*> m_list;
|
||||
};
|
||||
|
||||
#endif // PACKAGES_H
|
||||
94
libnymea-common/types/repositories.cpp
Normal file
94
libnymea-common/types/repositories.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include "repositories.h"
|
||||
#include "repository.h"
|
||||
|
||||
Repositories::Repositories(QObject *parent): QAbstractListModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Repositories::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_list.count();
|
||||
}
|
||||
|
||||
QVariant Repositories::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
switch (role) {
|
||||
case RoleId:
|
||||
return m_list.at(index.row())->id();
|
||||
case RoleDisplayName:
|
||||
return m_list.at(index.row())->displayName();
|
||||
case RoleEnabled:
|
||||
return m_list.at(index.row())->enabled();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> Repositories::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(RoleId, "id");
|
||||
roles.insert(RoleDisplayName, "displayName");
|
||||
roles.insert(RoleEnabled, "enabled");
|
||||
return roles;
|
||||
}
|
||||
|
||||
Repository *Repositories::get(int index) const
|
||||
{
|
||||
if (index >= 0 && index < m_list.count()) {
|
||||
return m_list.at(index);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Repository *Repositories::getRepository(const QString &id) const
|
||||
{
|
||||
foreach (Repository *repo, m_list) {
|
||||
if (repo->id() == id) {
|
||||
return repo;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Repositories::addRepository(Repository *repository)
|
||||
{
|
||||
repository->setParent(this);
|
||||
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||
m_list.append(repository);
|
||||
connect(repository, &Repository::enabledChanged, this, [this, repository](){
|
||||
QModelIndex idx = index(m_list.indexOf(repository));
|
||||
emit dataChanged(idx, idx, {RoleEnabled});
|
||||
});
|
||||
endInsertRows();
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
void Repositories::removeRepository(const QString &repositoryId)
|
||||
{
|
||||
int idx = -1;
|
||||
for (int i = 0; i < m_list.count(); i++) {
|
||||
if (m_list.at(i)->id() == repositoryId) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx < 0) {
|
||||
return;
|
||||
}
|
||||
beginRemoveRows(QModelIndex(), idx, idx);
|
||||
m_list.takeAt(idx)->deleteLater();
|
||||
endRemoveRows();
|
||||
emit countChanged();
|
||||
|
||||
}
|
||||
|
||||
void Repositories::clear()
|
||||
{
|
||||
beginResetModel();
|
||||
qDeleteAll(m_list);
|
||||
m_list.clear();
|
||||
endResetModel();
|
||||
emit countChanged();
|
||||
}
|
||||
40
libnymea-common/types/repositories.h
Normal file
40
libnymea-common/types/repositories.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef REPOSITORIES_H
|
||||
#define REPOSITORIES_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class Repository;
|
||||
|
||||
class Repositories : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||
public:
|
||||
enum Roles {
|
||||
RoleId,
|
||||
RoleDisplayName,
|
||||
RoleEnabled
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit Repositories(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE Repository* get(int index) const;
|
||||
Q_INVOKABLE Repository* getRepository(const QString &id) const;
|
||||
|
||||
void addRepository(Repository* repository);
|
||||
void removeRepository(const QString &repositoryId);
|
||||
void clear();
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
QList<Repository*> m_list;
|
||||
};
|
||||
|
||||
#endif // REPOSITORIES_H
|
||||
32
libnymea-common/types/repository.cpp
Normal file
32
libnymea-common/types/repository.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "repository.h"
|
||||
|
||||
Repository::Repository(const QString &id, const QString &displayName, QObject *parent):
|
||||
QObject(parent),
|
||||
m_id(id),
|
||||
m_displayName(displayName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString Repository::id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString Repository::displayName() const
|
||||
{
|
||||
return m_displayName;
|
||||
}
|
||||
|
||||
bool Repository::enabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
void Repository::setEnabled(bool enabled)
|
||||
{
|
||||
if (m_enabled != enabled) {
|
||||
m_enabled = enabled;
|
||||
emit enabledChanged();
|
||||
}
|
||||
}
|
||||
31
libnymea-common/types/repository.h
Normal file
31
libnymea-common/types/repository.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef REPOSITORY_H
|
||||
#define REPOSITORY_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Repository : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString id READ id CONSTANT)
|
||||
Q_PROPERTY(QString displayName READ displayName CONSTANT)
|
||||
Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged)
|
||||
|
||||
public:
|
||||
explicit Repository(const QString &id, const QString &displayName, QObject *parent = nullptr);
|
||||
|
||||
QString id() const;
|
||||
QString displayName() const;
|
||||
|
||||
bool enabled() const;
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
signals:
|
||||
void enabledChanged();
|
||||
|
||||
private:
|
||||
QString m_id;
|
||||
QString m_displayName;
|
||||
bool m_enabled = false;
|
||||
};
|
||||
|
||||
#endif // REPOSITORY_H
|
||||
@ -177,5 +177,9 @@
|
||||
<file>ui/images/network-wifi-offline.svg</file>
|
||||
<file>ui/images/network-wired-offline.svg</file>
|
||||
<file>ui/images/preferences-look-and-feel.svg</file>
|
||||
<file>ui/images/sensors/closable.svg</file>
|
||||
<file>ui/images/lock-closed.svg</file>
|
||||
<file>ui/images/lock-open.svg</file>
|
||||
<file>ui/images/system-update.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -180,5 +180,7 @@
|
||||
<file>ui/appsettings/LookAndFeelSettingsPage.qml</file>
|
||||
<file>ui/appsettings/AppLogPage.qml</file>
|
||||
<file>ui/magic/SelectStatePage.qml</file>
|
||||
<file>ui/system/SystemUpdatePage.qml</file>
|
||||
<file>ui/components/UpdateRunningOverlay.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -170,6 +170,8 @@ ApplicationWindow {
|
||||
return Qt.resolvedUrl("images/sensors/light.svg")
|
||||
case "presencesensor":
|
||||
return Qt.resolvedUrl("images/sensors/presence.svg")
|
||||
case "closablesensor":
|
||||
return Qt.resolvedUrl("images/sensors/closable.svg")
|
||||
case "media":
|
||||
case "mediacontroller":
|
||||
return Qt.resolvedUrl("images/mediaplayer-app-symbolic.svg")
|
||||
@ -210,7 +212,7 @@ ApplicationWindow {
|
||||
case "fingerprintreader":
|
||||
return Qt.resolvedUrl("images/fingerprint.svg")
|
||||
case "accesscontrol":
|
||||
return Qt.resolvedUrl("images/network-secure.svg");
|
||||
return Qt.resolvedUrl("images/lock-closed.svg");
|
||||
case "smartmeter":
|
||||
case "smartmeterconsumer":
|
||||
case "smartmeterproducer":
|
||||
@ -244,6 +246,7 @@ ApplicationWindow {
|
||||
"co2sensor": "turquoise",
|
||||
"daylightsensor": "gold",
|
||||
"presencesensor": "darkblue",
|
||||
"closablesensor": "green",
|
||||
"smartmeterproducer": "lightgreen",
|
||||
"smartmeterconsumer": "orange",
|
||||
"extendedsmartmeterproducer": "blue",
|
||||
|
||||
@ -155,6 +155,23 @@ Page {
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
Layout.fillWidth: true
|
||||
Material.elevation: layout.isGrid ? 1 : 0
|
||||
visible: engine.jsonRpcClient.ensureServerVersion("2.1")
|
||||
|
||||
padding: 0
|
||||
MeaListItemDelegate {
|
||||
width: parent.width
|
||||
iconName: "../images/system-update.svg"
|
||||
text: qsTr("System update")
|
||||
subText: qsTr("Update your %1:core system").arg(app.systemName)
|
||||
prominentSubText: false
|
||||
wrapTexts: false
|
||||
onClicked: pageStack.push(Qt.resolvedUrl("system/SystemUpdatePage.qml"))
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
Layout.fillWidth: true
|
||||
Material.elevation: layout.isGrid ? 1 : 0
|
||||
|
||||
44
nymea-app/ui/components/UpdateRunningOverlay.qml
Normal file
44
nymea-app/ui/components/UpdateRunningOverlay.qml
Normal file
@ -0,0 +1,44 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.2
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#99000000"
|
||||
visible: shown
|
||||
|
||||
property bool shown: false
|
||||
// Event eater
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
|
||||
ColorIcon {
|
||||
height: app.iconSize * 3
|
||||
width: height
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
name: Qt.resolvedUrl("../images/system-update.svg")
|
||||
color: app.accentColor
|
||||
PropertyAnimation on rotation {
|
||||
from: 0; to: 360;
|
||||
duration: 2000
|
||||
loops: Animation.Inifinite
|
||||
onStopped: start(); // No clue why loops won't work
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: app.margins * 2
|
||||
text: qsTr("An update operation is currently running.\nPlease wait for it to complete.")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: app.largeFont
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,6 +84,7 @@ DeviceListPageBase {
|
||||
ListElement { interfaceName: "co2sensor"; stateName: "co2" }
|
||||
ListElement { interfaceName: "daylightsensor"; stateName: "daylight" }
|
||||
ListElement { interfaceName: "presencesensor"; stateName: "isPresent" }
|
||||
ListElement { interfaceName: "closablesensor"; stateName: "closed" }
|
||||
ListElement { interfaceName: "heating"; stateName: "power" }
|
||||
ListElement { interfaceName: "thermostat"; stateName: "targetTemperature" }
|
||||
}
|
||||
@ -100,24 +101,45 @@ DeviceListPageBase {
|
||||
Layout.preferredHeight: app.iconSize * .8
|
||||
Layout.preferredWidth: height
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: app.interfaceToColor(model.interfaceName)
|
||||
name: app.interfaceToIcon(model.interfaceName)
|
||||
color: {
|
||||
switch (model.interfaceName) {
|
||||
case "closablesensor":
|
||||
return sensorValueDelegate.stateValue.value === true ? "green" : "red";
|
||||
default:
|
||||
return app.interfaceToColor(model.interfaceName)
|
||||
}
|
||||
}
|
||||
name: {
|
||||
switch (model.interfaceName) {
|
||||
case "closablesensor":
|
||||
return sensorValueDelegate.stateValue.value === true ? Qt.resolvedUrl("../images/lock-closed.svg") : Qt.resolvedUrl("../images/lock-open.svg");
|
||||
default:
|
||||
return app.interfaceToIcon(model.interfaceName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: sensorValueDelegate.stateType && sensorValueDelegate.stateType.type.toLowerCase() === "bool"
|
||||
? sensorValueDelegate.stateType.displayName
|
||||
: sensorValueDelegate.stateValue
|
||||
? "%1 %2".arg(Math.round(sensorValueDelegate.stateValue.value * 100) / 100).arg(sensorValueDelegate.stateType.unitString)
|
||||
: ""
|
||||
text: {
|
||||
switch (model.interfaceName) {
|
||||
case "closablesensor":
|
||||
return sensorValueDelegate.stateValue.value === true ? qsTr("is closed") : qsTr("is open");
|
||||
default:
|
||||
return sensorValueDelegate.stateType && sensorValueDelegate.stateType.type.toLowerCase() === "bool"
|
||||
? sensorValueDelegate.stateType.displayName
|
||||
: sensorValueDelegate.stateValue
|
||||
? "%1 %2".arg(Math.round(sensorValueDelegate.stateValue.value * 100) / 100).arg(sensorValueDelegate.stateType.unitString)
|
||||
: ""
|
||||
}
|
||||
}
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: app.smallFont
|
||||
}
|
||||
Led {
|
||||
id: led
|
||||
visible: sensorValueDelegate.stateType && sensorValueDelegate.stateType.type.toLowerCase() == "bool"
|
||||
visible: ["presencesensor", "daylightsensor"].indexOf(model.interfaceName) >= 0
|
||||
state: visible && sensorValueDelegate.stateValue.value === true ? "on" : "off"
|
||||
}
|
||||
Item {
|
||||
|
||||
@ -11,7 +11,7 @@ ListView {
|
||||
interactive: contentHeight > height
|
||||
model: ListModel {
|
||||
Component.onCompleted: {
|
||||
var supportedInterfaces = ["temperaturesensor", "humiditysensor", "pressuresensor", "moisturesensor", "lightsensor", "conductivitysensor", "noisesensor", "co2sensor", "presencesensor", "daylightsensor"]
|
||||
var supportedInterfaces = ["temperaturesensor", "humiditysensor", "pressuresensor", "moisturesensor", "lightsensor", "conductivitysensor", "noisesensor", "co2sensor", "presencesensor", "daylightsensor", "closablesensor"]
|
||||
for (var i = 0; i < supportedInterfaces.length; i++) {
|
||||
if (root.deviceClass.interfaces.indexOf(supportedInterfaces[i]) >= 0) {
|
||||
append({name: supportedInterfaces[i]});
|
||||
@ -38,7 +38,8 @@ ListView {
|
||||
"noisesensor": "noise",
|
||||
"co2sensor": "co2",
|
||||
"presencesensor": "isPresent",
|
||||
"daylightsensor": "daylight"
|
||||
"daylightsensor": "daylight",
|
||||
"closablesensor": "closed"
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,8 +73,22 @@ ListView {
|
||||
anchors.centerIn: parent
|
||||
height: app.iconSize * 4
|
||||
width: height
|
||||
name: app.interfaceToIcon(boolView.interfaceName)
|
||||
color: device.states.getState(boolView.stateType.id).value === true ? app.interfaceToColor(boolView.interfaceName) : keyColor
|
||||
name: {
|
||||
switch (boolView.interfaceName) {
|
||||
case "closablesensor":
|
||||
return device.states.getState(boolView.stateType.id).value === true ? Qt.resolvedUrl("../images/lock-closed.svg") : Qt.resolvedUrl("../images/lock-open.svg")
|
||||
default:
|
||||
return app.interfaceToIcon(boolView.interfaceName)
|
||||
}
|
||||
}
|
||||
color: {
|
||||
switch (boolView.interfaceName) {
|
||||
case "closablesensor":
|
||||
return device.states.getState(boolView.stateType.id).value === true ? "green" : "red"
|
||||
default:
|
||||
device.states.getState(boolView.stateType.id).value === true ? app.interfaceToColor(boolView.interfaceName) : keyColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
|
||||
175
nymea-app/ui/images/lock-closed.svg
Normal file
175
nymea-app/ui/images/lock-closed.svg
Normal file
@ -0,0 +1,175 @@
|
||||
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="96"
|
||||
height="96"
|
||||
id="svg4874"
|
||||
version="1.1"
|
||||
inkscape:version="0.91+devel r"
|
||||
viewBox="0 0 96 96.000001"
|
||||
sodipodi:docname="lock.svg">
|
||||
<defs
|
||||
id="defs4876" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6199992"
|
||||
inkscape:cx="5.4626288"
|
||||
inkscape:cy="25.355855"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g4780"
|
||||
showgrid="true"
|
||||
showborder="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid5451"
|
||||
empspacing="8" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="8,-8.0000001"
|
||||
id="guide4063" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="4,-8.0000001"
|
||||
id="guide4065" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,88.000001"
|
||||
id="guide4067" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,92.000001"
|
||||
id="guide4069" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="104,4"
|
||||
id="guide4071" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-5,8.0000001"
|
||||
id="guide4073" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="92,-8.0000001"
|
||||
id="guide4075" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="88,-8.0000001"
|
||||
id="guide4077" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,84.000001"
|
||||
id="guide4074" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="12,-8.0000001"
|
||||
id="guide4076" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-5,12"
|
||||
id="guide4078" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="84,-9.0000001"
|
||||
id="guide4080" />
|
||||
<sodipodi:guide
|
||||
position="48,-8.0000001"
|
||||
orientation="1,0"
|
||||
id="guide4170" />
|
||||
<sodipodi:guide
|
||||
position="-8,48"
|
||||
orientation="0,1"
|
||||
id="guide4172" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4879">
|
||||
<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>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(67.857146,-78.50504)">
|
||||
<g
|
||||
transform="matrix(0,-1,-1,0,373.50506,516.50504)"
|
||||
id="g4845"
|
||||
style="display:inline">
|
||||
<g
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-filename="next01.png"
|
||||
transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
|
||||
id="g4778"
|
||||
inkscape:label="Layer 1">
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,575.99999,611)"
|
||||
id="g4780"
|
||||
style="display:inline">
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
|
||||
id="rect4782"
|
||||
width="96.037987"
|
||||
height="96"
|
||||
x="-438.00244"
|
||||
y="345.36221"
|
||||
transform="scale(-1,1)" />
|
||||
<path
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 393.98438,425.36133 -2,0 -46.01758,0 0,-64 48.01758,0 0,64 z m -4,-4 0,-55.99805 -40.01758,0 0,55.99805 40.01758,0 z"
|
||||
id="rect4269"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 434.00087,393.36222 c 0,13.81562 -11.1845,25.00195 -25.00013,25.00195 l -16.0161,0 0,-4.00195 16.0161,0 c 11.66838,0 21.0005,-9.33162 21.0005,-21 0,-11.66838 -9.33212,-20.99805 -21.0005,-20.99805 l -16.0161,0 0,-4.00195 16.0161,0 c 13.81563,0 25.00013,11.18438 25.00013,25 z"
|
||||
id="rect4271"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
transform="matrix(0,-1,-1,0,0,0)"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="m -397.36221,-377.9787 8,-2.00079 0,20.00794 -8,0 z"
|
||||
id="rect4280"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
194
nymea-app/ui/images/lock-open.svg
Normal file
194
nymea-app/ui/images/lock-open.svg
Normal file
@ -0,0 +1,194 @@
|
||||
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="96"
|
||||
height="96"
|
||||
id="svg4874"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
viewBox="0 0 96 96.000001"
|
||||
sodipodi:docname="lock-open.svg">
|
||||
<defs
|
||||
id="defs4876" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.239998"
|
||||
inkscape:cx="43.592981"
|
||||
inkscape:cy="47.834493"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g4780"
|
||||
showgrid="true"
|
||||
showborder="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="2792"
|
||||
inkscape:window-height="1698"
|
||||
inkscape:window-x="88"
|
||||
inkscape:window-y="44"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid5451"
|
||||
empspacing="8" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="8,-8.0000001"
|
||||
id="guide4063"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="4,-8.0000001"
|
||||
id="guide4065"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,88.000001"
|
||||
id="guide4067"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,92.000001"
|
||||
id="guide4069"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="104,4"
|
||||
id="guide4071"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-5,8.0000001"
|
||||
id="guide4073"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="92,-8.0000001"
|
||||
id="guide4075"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="88,-8.0000001"
|
||||
id="guide4077"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,84.000001"
|
||||
id="guide4074"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="12,-8.0000001"
|
||||
id="guide4076"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-5,12"
|
||||
id="guide4078"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="84,-9.0000001"
|
||||
id="guide4080"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="48,-8.0000001"
|
||||
orientation="1,0"
|
||||
id="guide4170"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="-8,48"
|
||||
orientation="0,1"
|
||||
id="guide4172"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4879">
|
||||
<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>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(67.857146,-78.50504)">
|
||||
<g
|
||||
transform="matrix(0,-1,-1,0,373.50506,516.50504)"
|
||||
id="g4845"
|
||||
style="display:inline">
|
||||
<g
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-filename="next01.png"
|
||||
transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
|
||||
id="g4778"
|
||||
inkscape:label="Layer 1">
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,575.99999,611)"
|
||||
id="g4780"
|
||||
style="display:inline">
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
|
||||
id="rect4782"
|
||||
width="96.037987"
|
||||
height="96"
|
||||
x="-438.00244"
|
||||
y="345.36221"
|
||||
transform="scale(-1,1)" />
|
||||
<path
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 393.98438,425.36133 -2,0 -46.01758,0 0,-64 48.01758,0 0,64 z m -4,-4 0,-55.99805 -40.01758,0 0,55.99805 40.01758,0 z"
|
||||
id="rect4269"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
transform="matrix(0,-1,-1,0,0,0)"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="m -397.36221,-377.9787 8,-2.00079 0,20.00794 -8,0 z"
|
||||
id="rect4280"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 434.00086,393.36221 c 0,13.81562 -11.18449,25.00196 -25.00012,25.00196 h -16.0161 v -4.00196 h 16.0161 c 11.66838,0 21.00049,-9.33162 21.00049,-21 0,-8.90954 -5.45053,-16.43796 -13.21812,-19.50781 l 1.56898,-3.66211 c 9.17277,3.70153 15.64877,12.66514 15.64877,23.16992 z m -30.01187,-20.99804 h -11.00435 v -4.00196 h 11.00435 z"
|
||||
id="rect4271-3" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.4 KiB |
175
nymea-app/ui/images/sensors/closable.svg
Normal file
175
nymea-app/ui/images/sensors/closable.svg
Normal file
@ -0,0 +1,175 @@
|
||||
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="96"
|
||||
height="96"
|
||||
id="svg4874"
|
||||
version="1.1"
|
||||
inkscape:version="0.91+devel r"
|
||||
viewBox="0 0 96 96.000001"
|
||||
sodipodi:docname="lock.svg">
|
||||
<defs
|
||||
id="defs4876" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6199992"
|
||||
inkscape:cx="5.4626288"
|
||||
inkscape:cy="25.355855"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g4780"
|
||||
showgrid="true"
|
||||
showborder="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid5451"
|
||||
empspacing="8" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="8,-8.0000001"
|
||||
id="guide4063" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="4,-8.0000001"
|
||||
id="guide4065" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,88.000001"
|
||||
id="guide4067" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,92.000001"
|
||||
id="guide4069" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="104,4"
|
||||
id="guide4071" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-5,8.0000001"
|
||||
id="guide4073" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="92,-8.0000001"
|
||||
id="guide4075" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="88,-8.0000001"
|
||||
id="guide4077" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-8,84.000001"
|
||||
id="guide4074" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="12,-8.0000001"
|
||||
id="guide4076" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="-5,12"
|
||||
id="guide4078" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="84,-9.0000001"
|
||||
id="guide4080" />
|
||||
<sodipodi:guide
|
||||
position="48,-8.0000001"
|
||||
orientation="1,0"
|
||||
id="guide4170" />
|
||||
<sodipodi:guide
|
||||
position="-8,48"
|
||||
orientation="0,1"
|
||||
id="guide4172" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4879">
|
||||
<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>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(67.857146,-78.50504)">
|
||||
<g
|
||||
transform="matrix(0,-1,-1,0,373.50506,516.50504)"
|
||||
id="g4845"
|
||||
style="display:inline">
|
||||
<g
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-filename="next01.png"
|
||||
transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
|
||||
id="g4778"
|
||||
inkscape:label="Layer 1">
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,575.99999,611)"
|
||||
id="g4780"
|
||||
style="display:inline">
|
||||
<rect
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
|
||||
id="rect4782"
|
||||
width="96.037987"
|
||||
height="96"
|
||||
x="-438.00244"
|
||||
y="345.36221"
|
||||
transform="scale(-1,1)" />
|
||||
<path
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 393.98438,425.36133 -2,0 -46.01758,0 0,-64 48.01758,0 0,64 z m -4,-4 0,-55.99805 -40.01758,0 0,55.99805 40.01758,0 z"
|
||||
id="rect4269"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079155;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 434.00087,393.36222 c 0,13.81562 -11.1845,25.00195 -25.00013,25.00195 l -16.0161,0 0,-4.00195 16.0161,0 c 11.66838,0 21.0005,-9.33162 21.0005,-21 0,-11.66838 -9.33212,-20.99805 -21.0005,-20.99805 l -16.0161,0 0,-4.00195 16.0161,0 c 13.81563,0 25.00013,11.18438 25.00013,25 z"
|
||||
id="rect4271"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
transform="matrix(0,-1,-1,0,0,0)"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
d="m -397.36221,-377.9787 8,-2.00079 0,20.00794 -8,0 z"
|
||||
id="rect4280"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
21
nymea-app/ui/images/system-update.svg
Normal file
21
nymea-app/ui/images/system-update.svg
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg id="svg4874" width="96" height="96" version="1.1" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata id="metadata4879">
|
||||
<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 id="layer1" transform="translate(67.857 -78.505)">
|
||||
<rect id="rect4782-35" transform="rotate(90)" x="78.505" y="-28.143" width="96" height="96" style="color:#000000;fill:none"/>
|
||||
<path id="path4116-8" d="m-19.856 84.505c-23.173 0-42 18.827-42 41.999 0 23.172 18.827 41.999 42 41.999 23.173 0 42-18.827 42-41.999 0-23.172-18.827-41.999-42-41.999zm0 3.9984c21.01 0 38 16.99 38 38.001 0 21.011-16.99 38.001-38 38.001-21.01 0-38-16.99-38-38.001 0-21.011 16.99-38.001 38-38.001z" style="color-rendering:auto;color:#000000;fill:#808080;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:none;font-variant-numeric:normal;font-variant-position:normal;image-rendering:auto;isolation:auto;mix-blend-mode:normal;shape-padding:0;shape-rendering:auto;solid-color:#000000;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
|
||||
<path id="ellipse4183" d="m-21.663 100.57c2.815-0.19766 5.6957 0.0631 8.5352 0.8239 11.358 3.0433 19.27 13.356 19.27 25.113h-4c0-9.9674-6.6798-18.67-16.307-21.249-9.6269-2.5795-19.761 1.618-24.744 10.25l-3.4648-1.9992c4.4092-7.6369 12.266-12.346 20.711-12.938z" style="color-rendering:auto;color:#000000;fill:#808080;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:none;font-variant-numeric:normal;font-variant-position:normal;image-rendering:auto;isolation:auto;mix-blend-mode:normal;shape-padding:0;shape-rendering:auto;solid-color:#000000;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
|
||||
<path id="path4187" d="m-18.052 152.44c-2.815 0.19767-5.6957-0.0612-8.5352-0.82193-11.358-3.0433-19.27-13.356-19.27-25.113h4c0 9.9674 6.6798 18.67 16.307 21.249 9.6269 2.5795 19.761-1.6181 24.744-10.25l3.4668 1.9992c-4.4092 7.6369-12.268 12.344-20.713 12.936z" style="color-rendering:auto;color:#000000;fill:#808080;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:none;font-variant-numeric:normal;font-variant-position:normal;image-rendering:auto;isolation:auto;mix-blend-mode:normal;shape-padding:0;shape-rendering:auto;solid-color:#000000;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
|
||||
<path id="path5918" d="m-6.5222 122.42 18.665-7.1843c-0.22375 3.2869-0.5836 6.6835-1.0752 10.19-0.50612 3.481-1.1013 6.8801-1.7886 10.196-2.6998-2.0116-5.4056-4.1394-8.1157-6.3818-2.7182-2.2723-5.2797-4.5458-7.686-6.8213z" style="color:#000000;fill:#808080"/>
|
||||
<path id="path4471" d="m-33.192 130.59-18.665 7.1843c0.22375-3.2869 0.5836-6.6834 1.0752-10.19 0.50612-3.481 1.1013-6.8801 1.7886-10.196 2.6998 2.0116 5.4056 4.1394 8.1157 6.3818 2.7182 2.2723 5.2797 4.5458 7.686 6.8213z" style="color:#000000;fill:#808080"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
@ -428,6 +428,7 @@ MainPageTile {
|
||||
ListElement { ifaceName: "pressuresensor"; stateName: "pressure" }
|
||||
ListElement { ifaceName: "daylightsensor"; stateName: "daylight" }
|
||||
ListElement { ifaceName: "presencesensor"; stateName: "isPresent" }
|
||||
ListElement { ifaceName: "closablesensor"; stateName: "closed" }
|
||||
ListElement { ifaceName: "lightsensor"; stateName: "lightIntensity" }
|
||||
ListElement { ifaceName: "co2sensor"; stateName: "co2" }
|
||||
ListElement { ifaceName: "conductivity"; stateName: "conductivity" }
|
||||
@ -511,7 +512,7 @@ MainPageTile {
|
||||
Led {
|
||||
Layout.preferredHeight: app.iconSize * .5
|
||||
Layout.preferredWidth: height
|
||||
state: sensorsRoot.shownStateType && sensorsRoot.device.stateValue(sensorsRoot.shownStateType.id) === true ? "on" : "off"
|
||||
state: sensorsRoot.shownStateType && sensorsRoot.device.states.getState(sensorsRoot.shownStateType.id).value === true ? "on" : "off"
|
||||
visible: sensorsRoot.shownStateType && sensorsRoot.shownStateType.type.toLowerCase() === "bool"
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,5 +93,22 @@ Page {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Reboot %1:core").arg(app.systemName)
|
||||
visible: engine.systemController.powerManagementAvailable
|
||||
onClicked: {
|
||||
engine.systemController.reboot()
|
||||
}
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Shutdown %1:core").arg(app.systemName)
|
||||
visible: engine.systemController.powerManagementAvailable
|
||||
onClicked: {
|
||||
engine.systemController.shutdown()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
266
nymea-app/ui/system/SystemUpdatePage.qml
Normal file
266
nymea-app/ui/system/SystemUpdatePage.qml
Normal file
@ -0,0 +1,266 @@
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Controls.Material 2.1
|
||||
import QtQuick.Layouts 1.3
|
||||
import "../components"
|
||||
import Nymea 1.0
|
||||
|
||||
Page {
|
||||
id: root
|
||||
header: GuhHeader {
|
||||
text: qsTr("System update")
|
||||
backButtonVisible: true
|
||||
onBackPressed: pageStack.pop()
|
||||
}
|
||||
|
||||
PackagesFilterModel {
|
||||
id: updatesModel
|
||||
packages: engine.systemController.packages
|
||||
updatesOnly: true
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: contentColumn
|
||||
anchors.fill: parent
|
||||
|
||||
MeaListItemDelegate {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Configure updates")
|
||||
onClicked: {
|
||||
pageStack.push(repositoryListComponent)
|
||||
}
|
||||
}
|
||||
|
||||
MeaListItemDelegate {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Show all packages")
|
||||
onClicked: {
|
||||
pageStack.push(packageListComponent, {packages: engine.systemController.packages})
|
||||
}
|
||||
}
|
||||
|
||||
ThinDivider {}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: app.margins
|
||||
elide: Text.ElideRight
|
||||
text: updatesModel.count === 0 ? qsTr("Your system is up to date.") : qsTr("There are %1 updates available.").arg(updatesModel.count)
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: app.margins
|
||||
text: qsTr("Update all")
|
||||
visible: updatesModel.count > 0
|
||||
onClicked: {
|
||||
var dialog = Qt.createComponent(Qt.resolvedUrl("../components/MeaDialog.qml"));
|
||||
var text = qsTr("This will start a system update. Note that the update might take several minutes and your %1:core might not be functioning properly during this time and restart during the process.\nDo you want to proceed?").arg(app.systemName)
|
||||
var popup = dialog.createObject(app,
|
||||
{
|
||||
headerIcon: "../images/system-update.svg",
|
||||
title: qsTr("System update"),
|
||||
text: text,
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
});
|
||||
popup.open();
|
||||
popup.accepted.connect(function() {
|
||||
engine.systemController.updatePackages()
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: updatesModel
|
||||
clip: true
|
||||
delegate: MeaListItemDelegate {
|
||||
width: parent.width
|
||||
text: model.displayName
|
||||
subText: model.candidateVersion
|
||||
prominentSubText: false
|
||||
iconName: model.updateAvailable
|
||||
? Qt.resolvedUrl("../images/system-update.svg")
|
||||
: Qt.resolvedUrl("../images/view-" + (model.installedVersion.length > 0 ? "expand" : "collapse") + ".svg")
|
||||
iconColor: model.updateAvailable
|
||||
? "green"
|
||||
: model.installedVersion.length > 0 ? "blue" : iconKeyColor
|
||||
onClicked: {
|
||||
pageStack.push(packageDetailsComponent, {pkg: updatesModel.get(index)})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: repositoryListComponent
|
||||
Page {
|
||||
id: repositoryListPage
|
||||
header: GuhHeader {
|
||||
text: qsTr("Configure update sources")
|
||||
onBackPressed: pageStack.pop()
|
||||
}
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
model: engine.systemController.repositories
|
||||
delegate: CheckDelegate {
|
||||
width: parent.width
|
||||
text: model.displayName
|
||||
checked: model.enabled
|
||||
onClicked: {
|
||||
if (checked) {
|
||||
var dialog = Qt.createComponent(Qt.resolvedUrl("../components/MeaDialog.qml"));
|
||||
var text = qsTr("Enabling additional software sources allows to install unreleased %1:core packages.\nThis can potentially break your system and lead to problems.\nPlease only use this if you are sure you want this and consider reporting the issues you find when testing unreleased channels.").arg(app.systemName)
|
||||
var popup = dialog.createObject(app,
|
||||
{
|
||||
headerIcon: "../images/dialog-warning-symbolic.svg",
|
||||
title: qsTr("Enable package source"),
|
||||
text: text,
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
});
|
||||
popup.open();
|
||||
popup.accepted.connect(function() {
|
||||
engine.systemController.enableRepository(model.id, true)
|
||||
})
|
||||
popup.rejected.connect(function() {
|
||||
checked = false
|
||||
})
|
||||
} else {
|
||||
engine.systemController.enableRepository(model.id, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateRunningOverlay {
|
||||
visible: engine.systemController.updateRunning
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: packageListComponent
|
||||
Page {
|
||||
id: packageListPage
|
||||
|
||||
property var packages: null
|
||||
|
||||
header: GuhHeader {
|
||||
text: qsTr("All packages")
|
||||
onBackPressed: pageStack.pop()
|
||||
}
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
model: PackagesFilterModel {
|
||||
id: filterModel
|
||||
packages: packageListPage.packages
|
||||
}
|
||||
delegate: MeaListItemDelegate {
|
||||
width: parent.width
|
||||
text: model.displayName
|
||||
subText: model.candidateVersion
|
||||
prominentSubText: false
|
||||
iconName: model.updateAvailable
|
||||
? Qt.resolvedUrl("../images/system-update.svg")
|
||||
: Qt.resolvedUrl("../images/view-" + (model.installedVersion.length > 0 ? "expand" : "collapse") + ".svg")
|
||||
iconColor: model.updateAvailable
|
||||
? "green"
|
||||
: model.installedVersion.length > 0 ? "blue" : iconKeyColor
|
||||
onClicked: {
|
||||
pageStack.push(packageDetailsComponent, {pkg: filterModel.get(index)})
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateRunningOverlay {
|
||||
visible: engine.systemController.updateRunning
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: packageDetailsComponent
|
||||
Page {
|
||||
id: packageDetailsPage
|
||||
|
||||
property Package pkg: null
|
||||
|
||||
header: GuhHeader {
|
||||
text: pkg.displayName
|
||||
onBackPressed: pageStack.pop()
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||
columns: app.landscape ? 2 : 1
|
||||
MeaListItemDelegate {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Installed version:")
|
||||
subText: packageDetailsPage.pkg.installedVersion
|
||||
progressive: false
|
||||
}
|
||||
|
||||
MeaListItemDelegate {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Candidate version:")
|
||||
subText: packageDetailsPage.pkg.candidateVersion
|
||||
visible: packageDetailsPage.pkg.updateAvailable || packageDetailsPage.pkg.installedVersion.length === 0
|
||||
progressive: false
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: app.margins
|
||||
visible: packageDetailsPage.pkg.updateAvailable || packageDetailsPage.pkg.installedVersion.length === 0
|
||||
text: packageDetailsPage.pkg.updateAvailable ? qsTr("Update") : qsTr("Install")
|
||||
onClicked: {
|
||||
var dialog = Qt.createComponent(Qt.resolvedUrl("../components/MeaDialog.qml"));
|
||||
var text = qsTr("This will start a system update. Note that the update might take several minutes and your %1:core might not be functioning properly during this time and restart during the process.\nDo you want to proceed?").arg(app.systemName)
|
||||
var popup = dialog.createObject(app,
|
||||
{
|
||||
headerIcon: "../images/system-update.svg",
|
||||
title: qsTr("Start update"),
|
||||
text: text,
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
});
|
||||
popup.open();
|
||||
popup.accepted.connect(function() {
|
||||
engine.systemController.updatePackages(packageDetailsPage.pkg.id)
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: app.margins
|
||||
text: qsTr("Remove")
|
||||
visible: packageDetailsPage.pkg.canRemove
|
||||
onClicked: {
|
||||
var dialog = Qt.createComponent(Qt.resolvedUrl("../components/MeaDialog.qml"));
|
||||
var text = qsTr("This will start a system update. Note that the update might take several minutes and your %1:core might not be functioning properly during this time and restart during the process.\nDo you want to proceed?").arg(app.systemName)
|
||||
var popup = dialog.createObject(app,
|
||||
{
|
||||
headerIcon: "../images/system-update.svg",
|
||||
title: qsTr("Remove package"),
|
||||
text: text,
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
});
|
||||
popup.open();
|
||||
popup.accepted.connect(function() {
|
||||
engine.systemController.removePackages(packageDetailsPage.pkg.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
UpdateRunningOverlay {
|
||||
visible: engine.systemController.updateRunning
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UpdateRunningOverlay {
|
||||
visible: engine.systemController.updateRunning
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user