Merge PR #417: Make plugin issues more visible to the user
This commit is contained in:
commit
1d4676b50f
@ -457,7 +457,7 @@ void DeviceManager::savePluginConfig(const QUuid &pluginId)
|
|||||||
ThingGroup *DeviceManager::createGroup(Interface *interface, DevicesProxy *things)
|
ThingGroup *DeviceManager::createGroup(Interface *interface, DevicesProxy *things)
|
||||||
{
|
{
|
||||||
ThingGroup* group = new ThingGroup(this, interface->createDeviceClass(), things, this);
|
ThingGroup* group = new ThingGroup(this, interface->createDeviceClass(), things, this);
|
||||||
group->setSetupStatus(Device::DeviceSetupStatusComplete, QString());
|
group->setSetupStatus(Device::ThingSetupStatusComplete, QString());
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,46 +40,52 @@ Devices::Devices(QObject *parent) :
|
|||||||
|
|
||||||
QList<Device *> Devices::devices()
|
QList<Device *> Devices::devices()
|
||||||
{
|
{
|
||||||
return m_devices;
|
return m_things;
|
||||||
}
|
}
|
||||||
|
|
||||||
Device *Devices::get(int index) const
|
Device *Devices::get(int index) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= m_devices.count()) {
|
if (index < 0 || index >= m_things.count()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return m_devices.at(index);
|
return m_things.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Device *Devices::getDevice(const QUuid &deviceId) const
|
Device *Devices::getThing(const QUuid &thingId) const
|
||||||
{
|
{
|
||||||
foreach (Device *device, m_devices) {
|
foreach (Device *thing, m_things) {
|
||||||
if (device->id() == deviceId) {
|
if (thing->id() == thingId) {
|
||||||
return device;
|
return thing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Device *Devices::getDevice(const QUuid &deviceId) const
|
||||||
|
{
|
||||||
|
return getThing(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
int Devices::rowCount(const QModelIndex &parent) const
|
int Devices::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(parent)
|
Q_UNUSED(parent)
|
||||||
return m_devices.count();
|
return m_things.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant Devices::data(const QModelIndex &index, int role) const
|
QVariant Devices::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (index.row() < 0 || index.row() >= m_devices.count())
|
if (index.row() < 0 || index.row() >= m_things.count())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
Device *thing = m_devices.at(index.row());
|
Device *thing = m_things.at(index.row());
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case RoleName:
|
case RoleName:
|
||||||
return thing->name();
|
return thing->name();
|
||||||
case RoleId:
|
case RoleId:
|
||||||
return thing->id().toString();
|
return thing->id().toString();
|
||||||
case RoleDeviceClass:
|
case RoleDeviceClass:
|
||||||
return thing->deviceClassId().toString();
|
case RoleThingClass:
|
||||||
|
return thing->thingClassId().toString();
|
||||||
case RoleParentDeviceId:
|
case RoleParentDeviceId:
|
||||||
return thing->parentDeviceId().toString();
|
return thing->parentDeviceId().toString();
|
||||||
case RoleSetupStatus:
|
case RoleSetupStatus:
|
||||||
@ -97,22 +103,22 @@ QVariant Devices::data(const QModelIndex &index, int role) const
|
|||||||
void Devices::addDevice(Device *device)
|
void Devices::addDevice(Device *device)
|
||||||
{
|
{
|
||||||
device->setParent(this);
|
device->setParent(this);
|
||||||
beginInsertRows(QModelIndex(), m_devices.count(), m_devices.count());
|
beginInsertRows(QModelIndex(), m_things.count(), m_things.count());
|
||||||
// qDebug() << "Devices: add device" << device->name();
|
// qDebug() << "Devices: add device" << device->name();
|
||||||
m_devices.append(device);
|
m_things.append(device);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
connect(device, &Device::nameChanged, this, [device, this]() {
|
connect(device, &Device::nameChanged, this, [device, this]() {
|
||||||
int idx = m_devices.indexOf(device);
|
int idx = m_things.indexOf(device);
|
||||||
if (idx < 0) return;
|
if (idx < 0) return;
|
||||||
emit dataChanged(index(idx), index(idx), {RoleName});
|
emit dataChanged(index(idx), index(idx), {RoleName});
|
||||||
});
|
});
|
||||||
connect(device, &Device::setupStatusChanged, this, [device, this]() {
|
connect(device, &Device::setupStatusChanged, this, [device, this]() {
|
||||||
int idx = m_devices.indexOf(device);
|
int idx = m_things.indexOf(device);
|
||||||
if (idx < 0) return;
|
if (idx < 0) return;
|
||||||
emit dataChanged(index(idx), index(idx), {RoleSetupStatus, RoleSetupDisplayMessage});
|
emit dataChanged(index(idx), index(idx), {RoleSetupStatus, RoleSetupDisplayMessage});
|
||||||
});
|
});
|
||||||
connect(device->states(), &States::dataChanged, this, [device, this]() {
|
connect(device->states(), &States::dataChanged, this, [device, this]() {
|
||||||
int idx = m_devices.indexOf(device);
|
int idx = m_things.indexOf(device);
|
||||||
if (idx < 0) return;
|
if (idx < 0) return;
|
||||||
emit dataChanged(index(idx), index(idx));
|
emit dataChanged(index(idx), index(idx));
|
||||||
});
|
});
|
||||||
@ -122,10 +128,10 @@ void Devices::addDevice(Device *device)
|
|||||||
|
|
||||||
void Devices::removeDevice(Device *device)
|
void Devices::removeDevice(Device *device)
|
||||||
{
|
{
|
||||||
int index = m_devices.indexOf(device);
|
int index = m_things.indexOf(device);
|
||||||
beginRemoveRows(QModelIndex(), index, index);
|
beginRemoveRows(QModelIndex(), index, index);
|
||||||
qDebug() << "Devices: removed device" << device->name();
|
qDebug() << "Devices: removed device" << device->name();
|
||||||
m_devices.takeAt(index)->deleteLater();
|
m_things.takeAt(index)->deleteLater();
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
emit countChanged();
|
emit countChanged();
|
||||||
emit thingRemoved(device);
|
emit thingRemoved(device);
|
||||||
@ -134,8 +140,8 @@ void Devices::removeDevice(Device *device)
|
|||||||
void Devices::clearModel()
|
void Devices::clearModel()
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
qDeleteAll(m_devices);
|
qDeleteAll(m_things);
|
||||||
m_devices.clear();
|
m_things.clear();
|
||||||
endResetModel();
|
endResetModel();
|
||||||
emit countChanged();
|
emit countChanged();
|
||||||
}
|
}
|
||||||
@ -146,6 +152,7 @@ QHash<int, QByteArray> Devices::roleNames() const
|
|||||||
roles[RoleName] = "name";
|
roles[RoleName] = "name";
|
||||||
roles[RoleId] = "id";
|
roles[RoleId] = "id";
|
||||||
roles[RoleDeviceClass] = "deviceClassId";
|
roles[RoleDeviceClass] = "deviceClassId";
|
||||||
|
roles[RoleThingClass] = "thingClassId";
|
||||||
roles[RoleParentDeviceId] = "parentDeviceId";
|
roles[RoleParentDeviceId] = "parentDeviceId";
|
||||||
roles[RoleSetupStatus] = "setupStatus";
|
roles[RoleSetupStatus] = "setupStatus";
|
||||||
roles[RoleSetupDisplayMessage] = "setupDisplayMessage";
|
roles[RoleSetupDisplayMessage] = "setupDisplayMessage";
|
||||||
|
|||||||
@ -46,6 +46,7 @@ public:
|
|||||||
RoleId,
|
RoleId,
|
||||||
RoleParentDeviceId,
|
RoleParentDeviceId,
|
||||||
RoleDeviceClass,
|
RoleDeviceClass,
|
||||||
|
RoleThingClass,
|
||||||
RoleSetupStatus,
|
RoleSetupStatus,
|
||||||
RoleSetupDisplayMessage,
|
RoleSetupDisplayMessage,
|
||||||
RoleInterfaces,
|
RoleInterfaces,
|
||||||
@ -58,6 +59,7 @@ public:
|
|||||||
QList<Device *> devices();
|
QList<Device *> devices();
|
||||||
|
|
||||||
Q_INVOKABLE Device *get(int index) const;
|
Q_INVOKABLE Device *get(int index) const;
|
||||||
|
Q_INVOKABLE Device *getThing(const QUuid &thingId) const;
|
||||||
Q_INVOKABLE Device *getDevice(const QUuid &deviceId) const;
|
Q_INVOKABLE Device *getDevice(const QUuid &deviceId) const;
|
||||||
|
|
||||||
int rowCount(const QModelIndex & parent = QModelIndex()) const;
|
int rowCount(const QModelIndex & parent = QModelIndex()) const;
|
||||||
@ -77,7 +79,7 @@ signals:
|
|||||||
void thingRemoved(Device *device);
|
void thingRemoved(Device *device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<Device *> m_devices;
|
QList<Device *> m_things;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -293,6 +293,21 @@ void DevicesProxy::setFilterDisconnected(bool filterDisconnected)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DevicesProxy::filterSetupFailed() const
|
||||||
|
{
|
||||||
|
return m_filterSetupFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicesProxy::setFilterSetupFailed(bool filterSetupFailed)
|
||||||
|
{
|
||||||
|
if (m_filterSetupFailed != filterSetupFailed) {
|
||||||
|
m_filterSetupFailed = filterSetupFailed;
|
||||||
|
emit filterSetupFailedChanged();
|
||||||
|
invalidateFilter();
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool DevicesProxy::groupByInterface() const
|
bool DevicesProxy::groupByInterface() const
|
||||||
{
|
{
|
||||||
return m_groupByInterface;
|
return m_groupByInterface;
|
||||||
@ -314,14 +329,19 @@ Device *DevicesProxy::get(int index) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Device *DevicesProxy::getDevice(const QUuid &deviceId) const
|
Device *DevicesProxy::getDevice(const QUuid &deviceId) const
|
||||||
|
{
|
||||||
|
return getThing(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Device *DevicesProxy::getThing(const QUuid &thingId) const
|
||||||
{
|
{
|
||||||
Devices *d = qobject_cast<Devices*>(sourceModel());
|
Devices *d = qobject_cast<Devices*>(sourceModel());
|
||||||
if (d) {
|
if (d) {
|
||||||
return d->getDevice(deviceId);
|
return d->getThing(thingId);
|
||||||
}
|
}
|
||||||
DevicesProxy *dp = qobject_cast<DevicesProxy*>(sourceModel());
|
DevicesProxy *dp = qobject_cast<DevicesProxy*>(sourceModel());
|
||||||
if (dp) {
|
if (dp) {
|
||||||
return dp->getDevice(deviceId);
|
return dp->getThing(thingId);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -426,6 +446,12 @@ bool DevicesProxy::filterAcceptsRow(int source_row, const QModelIndex &source_pa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_filterSetupFailed) {
|
||||||
|
if (device->setupStatus() != Device::ThingSetupStatusFailed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_nameFilter.isEmpty()) {
|
if (!m_nameFilter.isEmpty()) {
|
||||||
if (!device->name().toLower().contains(m_nameFilter.toLower().trimmed())) {
|
if (!device->name().toLower().contains(m_nameFilter.toLower().trimmed())) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -65,6 +65,8 @@ class DevicesProxy : public QSortFilterProxyModel
|
|||||||
// Setting this to true will imply filtering for "connectable" interface
|
// Setting this to true will imply filtering for "connectable" interface
|
||||||
Q_PROPERTY(bool filterDisconnected READ filterDisconnected WRITE setFilterDisconnected NOTIFY filterDisconnectedChanged)
|
Q_PROPERTY(bool filterDisconnected READ filterDisconnected WRITE setFilterDisconnected NOTIFY filterDisconnectedChanged)
|
||||||
|
|
||||||
|
Q_PROPERTY(bool filterSetupFailed READ filterSetupFailed WRITE setFilterSetupFailed NOTIFY filterSetupFailedChanged)
|
||||||
|
|
||||||
Q_PROPERTY(bool groupByInterface READ groupByInterface WRITE setGroupByInterface NOTIFY groupByInterfaceChanged)
|
Q_PROPERTY(bool groupByInterface READ groupByInterface WRITE setGroupByInterface NOTIFY groupByInterfaceChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -115,11 +117,15 @@ public:
|
|||||||
bool filterDisconnected() const;
|
bool filterDisconnected() const;
|
||||||
void setFilterDisconnected(bool filterDisconnected);
|
void setFilterDisconnected(bool filterDisconnected);
|
||||||
|
|
||||||
|
bool filterSetupFailed() const;
|
||||||
|
void setFilterSetupFailed(bool filterSetupFailed);
|
||||||
|
|
||||||
bool groupByInterface() const;
|
bool groupByInterface() const;
|
||||||
void setGroupByInterface(bool groupByInterface);
|
void setGroupByInterface(bool groupByInterface);
|
||||||
|
|
||||||
Q_INVOKABLE Device *get(int index) const;
|
Q_INVOKABLE Device *get(int index) const;
|
||||||
Q_INVOKABLE Device *getDevice(const QUuid &deviceId) const;
|
Q_INVOKABLE Device *getDevice(const QUuid &deviceId) const;
|
||||||
|
Q_INVOKABLE Device *getThing(const QUuid &thingId) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void engineChanged();
|
void engineChanged();
|
||||||
@ -137,6 +143,7 @@ signals:
|
|||||||
void showAnalogOutputsChanged();
|
void showAnalogOutputsChanged();
|
||||||
void filterBatteryCriticalChanged();
|
void filterBatteryCriticalChanged();
|
||||||
void filterDisconnectedChanged();
|
void filterDisconnectedChanged();
|
||||||
|
void filterSetupFailedChanged();
|
||||||
void groupByInterfaceChanged();
|
void groupByInterfaceChanged();
|
||||||
void countChanged();
|
void countChanged();
|
||||||
|
|
||||||
@ -160,6 +167,7 @@ private:
|
|||||||
|
|
||||||
bool m_filterBatteryCritical = false;
|
bool m_filterBatteryCritical = false;
|
||||||
bool m_filterDisconnected = false;
|
bool m_filterDisconnected = false;
|
||||||
|
bool m_filterSetupFailed = false;
|
||||||
|
|
||||||
bool m_groupByInterface = false;
|
bool m_groupByInterface = false;
|
||||||
|
|
||||||
|
|||||||
@ -250,16 +250,16 @@ Device* JsonTypes::unpackDevice(DeviceManager *deviceManager, const QVariantMap
|
|||||||
QString setupStatus = deviceMap.value("setupStatus").toString();
|
QString setupStatus = deviceMap.value("setupStatus").toString();
|
||||||
QString setupDisplayMessage = deviceMap.value("setupDisplayMessage").toString();
|
QString setupDisplayMessage = deviceMap.value("setupDisplayMessage").toString();
|
||||||
if (setupStatus == "DeviceSetupStatusNone" || setupStatus == "ThingSetupStatusNone") {
|
if (setupStatus == "DeviceSetupStatusNone" || setupStatus == "ThingSetupStatusNone") {
|
||||||
device->setSetupStatus(Device::DeviceSetupStatusNone, setupDisplayMessage);
|
device->setSetupStatus(Device::ThingSetupStatusNone, setupDisplayMessage);
|
||||||
} else if (setupStatus == "DeviceSetupStatusInProgress" || setupStatus == "ThingSetupStatusInProgress") {
|
} else if (setupStatus == "DeviceSetupStatusInProgress" || setupStatus == "ThingSetupStatusInProgress") {
|
||||||
device->setSetupStatus(Device::DeviceSetupStatusInProgress, setupDisplayMessage);
|
device->setSetupStatus(Device::ThingSetupStatusInProgress, setupDisplayMessage);
|
||||||
} else if (setupStatus == "DeviceSetupStatusComplete" || setupStatus == "ThingSetupStatusComplete") {
|
} else if (setupStatus == "DeviceSetupStatusComplete" || setupStatus == "ThingSetupStatusComplete") {
|
||||||
device->setSetupStatus(Device::DeviceSetupStatusComplete, setupDisplayMessage);
|
device->setSetupStatus(Device::ThingSetupStatusComplete, setupDisplayMessage);
|
||||||
} else if (setupStatus == "DeviceSetupStatusFailed" || setupStatus == "ThingSetupStatusFailed") {
|
} else if (setupStatus == "DeviceSetupStatusFailed" || setupStatus == "ThingSetupStatusFailed") {
|
||||||
device->setSetupStatus(Device::DeviceSetupStatusFailed, setupDisplayMessage);
|
device->setSetupStatus(Device::ThingSetupStatusFailed, setupDisplayMessage);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
device->setSetupStatus(deviceMap.value("setupComplete").toBool() ? Device::DeviceSetupStatusComplete : Device::DeviceSetupStatusNone, QString());
|
device->setSetupStatus(deviceMap.value("setupComplete").toBool() ? Device::ThingSetupStatusComplete : Device::ThingSetupStatusNone, QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
Params *params = device->params();
|
Params *params = device->params();
|
||||||
|
|||||||
@ -187,6 +187,8 @@ void registerQmlTypes() {
|
|||||||
qmlRegisterType<InterfacesModel>(uri, 1, 0, "InterfacesModel");
|
qmlRegisterType<InterfacesModel>(uri, 1, 0, "InterfacesModel");
|
||||||
qmlRegisterType<InterfacesSortModel>(uri, 1, 0, "InterfacesSortModel");
|
qmlRegisterType<InterfacesSortModel>(uri, 1, 0, "InterfacesSortModel");
|
||||||
|
|
||||||
|
qmlRegisterUncreatableType<DeviceClass>(uri, 1, 0, "ThingClass", "Can't create this in QML. Get it from the ThingClasses.");
|
||||||
|
qmlRegisterUncreatableType<DeviceClasses>(uri, 1, 0, "ThingClasses", "Can't create this in QML. Get it from the ThingManager.");
|
||||||
qmlRegisterUncreatableType<DeviceClass>(uri, 1, 0, "DeviceClass", "Can't create this in QML. Get it from the DeviceClasses.");
|
qmlRegisterUncreatableType<DeviceClass>(uri, 1, 0, "DeviceClass", "Can't create this in QML. Get it from the DeviceClasses.");
|
||||||
qmlRegisterUncreatableType<DeviceClasses>(uri, 1, 0, "DeviceClasses", "Can't create this in QML. Get it from the DeviceManager.");
|
qmlRegisterUncreatableType<DeviceClasses>(uri, 1, 0, "DeviceClasses", "Can't create this in QML. Get it from the DeviceManager.");
|
||||||
qmlRegisterType<DeviceClassesProxy>(uri, 1, 0, "DeviceClassesProxy");
|
qmlRegisterType<DeviceClassesProxy>(uri, 1, 0, "DeviceClassesProxy");
|
||||||
|
|||||||
@ -36,8 +36,8 @@
|
|||||||
|
|
||||||
ThingGroup::ThingGroup(DeviceManager *deviceManager, DeviceClass *deviceClass, DevicesProxy *devices, QObject *parent):
|
ThingGroup::ThingGroup(DeviceManager *deviceManager, DeviceClass *deviceClass, DevicesProxy *devices, QObject *parent):
|
||||||
Device(deviceManager, deviceClass, QUuid::createUuid(), parent),
|
Device(deviceManager, deviceClass, QUuid::createUuid(), parent),
|
||||||
m_deviceManager(deviceManager),
|
m_thingManager(deviceManager),
|
||||||
m_devices(devices)
|
m_things(devices)
|
||||||
{
|
{
|
||||||
deviceClass->setParent(this);
|
deviceClass->setParent(this);
|
||||||
|
|
||||||
@ -52,11 +52,11 @@ ThingGroup::ThingGroup(DeviceManager *deviceManager, DeviceClass *deviceClass, D
|
|||||||
syncStates();
|
syncStates();
|
||||||
setName(deviceClass->displayName());
|
setName(deviceClass->displayName());
|
||||||
|
|
||||||
connect(devices, &DevicesProxy::dataChanged, this, [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles){
|
connect(devices, &DevicesProxy::dataChanged, this, [this](const QModelIndex &/*topLeft*/, const QModelIndex &/*bottomRight*/, const QVector<int> &/*roles*/){
|
||||||
syncStates();
|
syncStates();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_deviceManager, &DeviceManager::executeActionReply, this, [this](const QVariantMap ¶ms){
|
connect(m_thingManager, &DeviceManager::executeActionReply, this, [this](const QVariantMap ¶ms){
|
||||||
int returningId = params.value("id").toInt();
|
int returningId = params.value("id").toInt();
|
||||||
foreach (int id, m_pendingActions.keys()) {
|
foreach (int id, m_pendingActions.keys()) {
|
||||||
if (m_pendingActions.value(id).contains(returningId)) {
|
if (m_pendingActions.value(id).contains(returningId)) {
|
||||||
@ -77,9 +77,9 @@ int ThingGroup::executeAction(const QString &actionName, const QVariantList &par
|
|||||||
QList<int> pendingIds;
|
QList<int> pendingIds;
|
||||||
|
|
||||||
qDebug() << "Execute action for group:" << this;
|
qDebug() << "Execute action for group:" << this;
|
||||||
for (int i = 0; i < m_devices->rowCount(); i++) {
|
for (int i = 0; i < m_things->rowCount(); i++) {
|
||||||
Device *device = m_devices->get(i);
|
Device *device = m_things->get(i);
|
||||||
if (device->setupStatus() != Device::DeviceSetupStatusComplete) {
|
if (device->setupStatus() != Device::ThingSetupStatusComplete) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ActionType *actionType = device->thingClass()->actionTypes()->findByName(actionName);
|
ActionType *actionType = device->thingClass()->actionTypes()->findByName(actionName);
|
||||||
@ -101,7 +101,7 @@ int ThingGroup::executeAction(const QString &actionName, const QVariantList &par
|
|||||||
|
|
||||||
qDebug() << "Initial params" << params;
|
qDebug() << "Initial params" << params;
|
||||||
qDebug() << "Executing" << device->id() << actionType->name() << finalParams;
|
qDebug() << "Executing" << device->id() << actionType->name() << finalParams;
|
||||||
int id = m_deviceManager->executeAction(device->id(), actionType->id(), finalParams);
|
int id = m_thingManager->executeAction(device->id(), actionType->id(), finalParams);
|
||||||
pendingIds.append(id);
|
pendingIds.append(id);
|
||||||
}
|
}
|
||||||
m_pendingActions.insert(++m_idCounter, pendingIds);
|
m_pendingActions.insert(++m_idCounter, pendingIds);
|
||||||
@ -118,8 +118,8 @@ void ThingGroup::syncStates()
|
|||||||
|
|
||||||
QVariant value;
|
QVariant value;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int j = 0; j < m_devices->rowCount(); j++) {
|
for (int j = 0; j < m_things->rowCount(); j++) {
|
||||||
Device *d = m_devices->get(j);
|
Device *d = m_things->get(j);
|
||||||
// Skip things that don't have the required state
|
// Skip things that don't have the required state
|
||||||
StateType *ds = d->thingClass()->stateTypes()->findByName(stateType->name());
|
StateType *ds = d->thingClass()->stateTypes()->findByName(stateType->name());
|
||||||
if (!ds) {
|
if (!ds) {
|
||||||
|
|||||||
@ -53,8 +53,8 @@ signals:
|
|||||||
void actionExecutionFinished(int id, const QString &status);
|
void actionExecutionFinished(int id, const QString &status);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceManager* m_deviceManager = nullptr;
|
DeviceManager* m_thingManager = nullptr;
|
||||||
DevicesProxy* m_devices = nullptr;
|
DevicesProxy* m_things = nullptr;
|
||||||
|
|
||||||
int m_idCounter = 0;
|
int m_idCounter = 0;
|
||||||
QHash<int, QList<int>> m_pendingActions;
|
QHash<int, QList<int>> m_pendingActions;
|
||||||
|
|||||||
@ -34,9 +34,9 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
Device::Device(DeviceManager *deviceManager, DeviceClass *thingClass, const QUuid &parentId, QObject *parent) :
|
Device::Device(DeviceManager *thingManager, DeviceClass *thingClass, const QUuid &parentId, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
m_deviceManager(deviceManager),
|
m_thingManager(thingManager),
|
||||||
m_parentId(parentId),
|
m_parentId(parentId),
|
||||||
m_thingClass(thingClass)
|
m_thingClass(thingClass)
|
||||||
{
|
{
|
||||||
@ -83,7 +83,7 @@ bool Device::isChild() const
|
|||||||
return !m_parentId.isNull();
|
return !m_parentId.isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::DeviceSetupStatus Device::setupStatus() const
|
Device::ThingSetupStatus Device::setupStatus() const
|
||||||
{
|
{
|
||||||
return m_setupStatus;
|
return m_setupStatus;
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ QString Device::setupDisplayMessage() const
|
|||||||
return m_setupDisplayMessage;
|
return m_setupDisplayMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::setSetupStatus(Device::DeviceSetupStatus setupStatus, const QString &displayMessage)
|
void Device::setSetupStatus(Device::ThingSetupStatus setupStatus, const QString &displayMessage)
|
||||||
{
|
{
|
||||||
if (m_setupStatus != setupStatus || m_setupDisplayMessage != displayMessage) {
|
if (m_setupStatus != setupStatus || m_setupDisplayMessage != displayMessage) {
|
||||||
m_setupStatus = setupStatus;
|
m_setupStatus = setupStatus;
|
||||||
@ -215,7 +215,7 @@ int Device::executeAction(const QString &actionName, const QVariantList ¶ms)
|
|||||||
}
|
}
|
||||||
finalParams.append(param);
|
finalParams.append(param);
|
||||||
}
|
}
|
||||||
return m_deviceManager->executeAction(m_id, actionType->id(), finalParams);
|
return m_thingManager->executeAction(m_id, actionType->id(), finalParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug &dbg, Device *thing)
|
QDebug operator<<(QDebug &dbg, Device *thing)
|
||||||
|
|||||||
@ -50,7 +50,7 @@ class Device : public QObject
|
|||||||
Q_PROPERTY(QUuid parentDeviceId READ parentDeviceId CONSTANT)
|
Q_PROPERTY(QUuid parentDeviceId READ parentDeviceId CONSTANT)
|
||||||
Q_PROPERTY(bool isChild READ isChild CONSTANT)
|
Q_PROPERTY(bool isChild READ isChild CONSTANT)
|
||||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||||
Q_PROPERTY(DeviceSetupStatus setupStatus READ setupStatus NOTIFY setupStatusChanged)
|
Q_PROPERTY(ThingSetupStatus setupStatus READ setupStatus NOTIFY setupStatusChanged)
|
||||||
Q_PROPERTY(QString setupDisplayMessage READ setupDisplayMessage NOTIFY setupStatusChanged)
|
Q_PROPERTY(QString setupDisplayMessage READ setupDisplayMessage NOTIFY setupStatusChanged)
|
||||||
Q_PROPERTY(Params *params READ params NOTIFY paramsChanged)
|
Q_PROPERTY(Params *params READ params NOTIFY paramsChanged)
|
||||||
Q_PROPERTY(Params *settings READ settings NOTIFY settingsChanged)
|
Q_PROPERTY(Params *settings READ settings NOTIFY settingsChanged)
|
||||||
@ -59,15 +59,15 @@ class Device : public QObject
|
|||||||
Q_PROPERTY(DeviceClass *thingClass READ thingClass CONSTANT)
|
Q_PROPERTY(DeviceClass *thingClass READ thingClass CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum DeviceSetupStatus {
|
enum ThingSetupStatus {
|
||||||
DeviceSetupStatusNone,
|
ThingSetupStatusNone,
|
||||||
DeviceSetupStatusInProgress,
|
ThingSetupStatusInProgress,
|
||||||
DeviceSetupStatusComplete,
|
ThingSetupStatusComplete,
|
||||||
DeviceSetupStatusFailed
|
ThingSetupStatusFailed
|
||||||
};
|
};
|
||||||
Q_ENUM(DeviceSetupStatus)
|
Q_ENUM(ThingSetupStatus)
|
||||||
|
|
||||||
explicit Device(DeviceManager *deviceManager, DeviceClass *thingClass, const QUuid &parentId = QUuid(), QObject *parent = nullptr);
|
explicit Device(DeviceManager *thingManager, DeviceClass *thingClass, const QUuid &parentId = QUuid(), QObject *parent = nullptr);
|
||||||
|
|
||||||
QUuid id() const;
|
QUuid id() const;
|
||||||
void setId(const QUuid &id);
|
void setId(const QUuid &id);
|
||||||
@ -80,9 +80,9 @@ public:
|
|||||||
QUuid parentDeviceId() const;
|
QUuid parentDeviceId() const;
|
||||||
bool isChild() const;
|
bool isChild() const;
|
||||||
|
|
||||||
DeviceSetupStatus setupStatus() const;
|
Device::ThingSetupStatus setupStatus() const;
|
||||||
QString setupDisplayMessage() const;
|
QString setupDisplayMessage() const;
|
||||||
void setSetupStatus(DeviceSetupStatus setupStatus, const QString &displayMessage);
|
void setSetupStatus(Device::ThingSetupStatus setupStatus, const QString &displayMessage);
|
||||||
|
|
||||||
Params *params() const;
|
Params *params() const;
|
||||||
void setParams(Params *params);
|
void setParams(Params *params);
|
||||||
@ -115,11 +115,11 @@ signals:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DeviceManager *m_deviceManager = nullptr;
|
DeviceManager *m_thingManager = nullptr;
|
||||||
QString m_name;
|
QString m_name;
|
||||||
QUuid m_id;
|
QUuid m_id;
|
||||||
QUuid m_parentId;
|
QUuid m_parentId;
|
||||||
DeviceSetupStatus m_setupStatus = DeviceSetupStatusNone;
|
ThingSetupStatus m_setupStatus = ThingSetupStatusNone;
|
||||||
QString m_setupDisplayMessage;
|
QString m_setupDisplayMessage;
|
||||||
Params *m_params = nullptr;
|
Params *m_params = nullptr;
|
||||||
Params *m_settings = nullptr;
|
Params *m_settings = nullptr;
|
||||||
|
|||||||
@ -125,8 +125,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
PushNotifications::instance()->connectClient();
|
PushNotifications::instance()->connectClient();
|
||||||
qmlRegisterSingletonType<PushNotifications>("Nymea", 1, 0, "PushNotifications", PushNotifications::pushNotificationsProvider);
|
qmlRegisterSingletonType<PushNotifications>("Nymea", 1, 0, "PushNotifications", PushNotifications::pushNotificationsProvider);
|
||||||
|
|
||||||
qmlRegisterSingletonType<AppLogController>("Nymea", 1, 0, "AppLogController", AppLogController::appLogControllerProvider);
|
qmlRegisterSingletonType<AppLogController>("Nymea", 1, 0, "AppLogController", AppLogController::appLogControllerProvider);
|
||||||
|
qmlRegisterSingletonType(QUrl("qrc:///ui/utils/NymeaUtils.qml"), "Nymea", 1, 0, "NymeaUtils" );
|
||||||
|
|
||||||
#ifdef BRANDING
|
#ifdef BRANDING
|
||||||
engine->rootContext()->setContextProperty("appBranding", BRANDING);
|
engine->rootContext()->setContextProperty("appBranding", BRANDING);
|
||||||
|
|||||||
@ -160,3 +160,8 @@ BR=$$BRANDING
|
|||||||
|
|
||||||
target.path = /usr/bin
|
target.path = /usr/bin
|
||||||
INSTALLS += target
|
INSTALLS += target
|
||||||
|
|
||||||
|
contains(ANDROID_TARGET_ARCH,) {
|
||||||
|
ANDROID_ABIS = \
|
||||||
|
armeabi-v7a
|
||||||
|
}
|
||||||
|
|||||||
@ -218,5 +218,9 @@
|
|||||||
<file>ui/mainviews/MediaView.qml</file>
|
<file>ui/mainviews/MediaView.qml</file>
|
||||||
<file>ui/components/ShuffleRepeatVolumeControl.qml</file>
|
<file>ui/components/ShuffleRepeatVolumeControl.qml</file>
|
||||||
<file>ui/components/MediaBrowser.qml</file>
|
<file>ui/components/MediaBrowser.qml</file>
|
||||||
|
<file>ui/utils/NymeaUtils.qml</file>
|
||||||
|
<file>ui/components/ConnectionStatusIcon.qml</file>
|
||||||
|
<file>ui/components/BatteryStatusIcon.qml</file>
|
||||||
|
<file>ui/components/SetupStatusIcon.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
28
nymea-app/ui/components/BatteryStatusIcon.qml
Normal file
28
nymea-app/ui/components/BatteryStatusIcon.qml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import Nymea 1.0
|
||||||
|
|
||||||
|
ColorIcon {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property Thing thing: null
|
||||||
|
|
||||||
|
readonly property bool hasBattery: batteryCriticalState !== null
|
||||||
|
readonly property bool hasBatteryLevel: batteryLevelState !== null
|
||||||
|
readonly property bool isCritical: batteryCriticalState && batteryCriticalState.value === true
|
||||||
|
readonly property int batteryLevel: batteryLevelState ? batteryLevelState.value : 0
|
||||||
|
|
||||||
|
readonly property State batteryCriticalState: thing.stateByName("batteryCritical")
|
||||||
|
readonly property State batteryLevelState: thing.stateByName("batteryLevel")
|
||||||
|
|
||||||
|
name: {
|
||||||
|
if (!hasBatteryLevel) {
|
||||||
|
if (isCritical) {
|
||||||
|
return "../images/battery/battery-020.svg"
|
||||||
|
}
|
||||||
|
return "../images/battery/battery-100.svg"
|
||||||
|
}
|
||||||
|
|
||||||
|
var rounded = Math.round(batteryLevel / 10) * 10
|
||||||
|
return "../images/battery/battery-" + NymeaUtils.pad(rounded, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
35
nymea-app/ui/components/ConnectionStatusIcon.qml
Normal file
35
nymea-app/ui/components/ConnectionStatusIcon.qml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import Nymea 1.0
|
||||||
|
|
||||||
|
ColorIcon {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property Thing thing: null
|
||||||
|
|
||||||
|
readonly property bool isConnected: connectedState === null || connectedState.value === true
|
||||||
|
readonly property bool isWireless: thing.thingClass.interfaces.indexOf("wirelessconnectable") >= 0
|
||||||
|
readonly property bool hasSignalStrength: signalStrengthState !== null
|
||||||
|
|
||||||
|
readonly property State connectedState: thing.stateByName("connected")
|
||||||
|
readonly property State signalStrengthState: thing.stateByName("signalStrength")
|
||||||
|
|
||||||
|
name: {
|
||||||
|
if (!isWireless) {
|
||||||
|
return connectedState && connectedState.value === true ? "../images/network-wired.svg" : "../images/network-wired-offline.svg"
|
||||||
|
}
|
||||||
|
if (connectedState && connectedState.value === false) {
|
||||||
|
return "../images/network-wifi-offline.svg"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signalStrengthState && signalStrengthState.value === -1) {
|
||||||
|
return "../images/network-wifi.svg"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "../images/nm-signal-" + NymeaUtils.pad(Math.round(signalStrengthState.value * 4 / 100) * 25, 2) + ".svg"
|
||||||
|
}
|
||||||
|
|
||||||
|
color: connectedState && connectedState.value === false
|
||||||
|
? "red"
|
||||||
|
: signalStrengthState && signalStrengthState.value < 20
|
||||||
|
? "orange" : keyColor
|
||||||
|
}
|
||||||
@ -32,6 +32,7 @@ import QtQuick 2.9
|
|||||||
import QtQuick.Controls 2.2
|
import QtQuick.Controls 2.2
|
||||||
import QtQuick.Controls.Material 2.2
|
import QtQuick.Controls.Material 2.2
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.3
|
||||||
|
import Nymea 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@ -42,6 +43,9 @@ Item {
|
|||||||
property alias backgroundImage: background.source
|
property alias backgroundImage: background.source
|
||||||
property string text
|
property string text
|
||||||
property bool disconnected: false
|
property bool disconnected: false
|
||||||
|
property bool isWireless: false
|
||||||
|
property int signalStrength: 0
|
||||||
|
property int setupStatus: Thing.ThingSetupStatusNone
|
||||||
property bool batteryCritical: false
|
property bool batteryCritical: false
|
||||||
|
|
||||||
property alias contentItem: innerContent.children
|
property alias contentItem: innerContent.children
|
||||||
@ -143,18 +147,26 @@ Item {
|
|||||||
Row {
|
Row {
|
||||||
id: quickAlertPane
|
id: quickAlertPane
|
||||||
anchors { top: parent.top; right: parent.right; margins: app.margins }
|
anchors { top: parent.top; right: parent.right; margins: app.margins }
|
||||||
|
spacing: app.margins / 2
|
||||||
ColorIcon {
|
ColorIcon {
|
||||||
height: app.iconSize / 2
|
height: app.iconSize / 2
|
||||||
width: height
|
width: height
|
||||||
name: "../images/dialog-warning-symbolic.svg"
|
name: root.isWireless ? "../images/network-wifi-offline.svg" : "../images/network-wired-offline.svg"
|
||||||
color: "red"
|
color: root.disconnected ? "red" : "orange"
|
||||||
visible: root.disconnected
|
visible: root.setupStatus == Thing.ThingSetupStatusComplete && (root.disconnected || (root.isWireless && root.signalStrength < 20))
|
||||||
|
}
|
||||||
|
ColorIcon {
|
||||||
|
height: app.iconSize / 2
|
||||||
|
width: height
|
||||||
|
name: root.setupStatus === Thing.ThingSetupStatusFailed ? "../images/dialog-warning-symbolic.svg" : "../images/settings.svg"
|
||||||
|
color: root.setupStatus === Thing.ThingSetupStatusFailed ? "red" : keyColor
|
||||||
|
visible: root.setupStatus === Thing.ThingSetupStatusFailed || root.setupStatus === Thing.ThingSetupStatusInProgress
|
||||||
}
|
}
|
||||||
ColorIcon {
|
ColorIcon {
|
||||||
height: app.iconSize / 2
|
height: app.iconSize / 2
|
||||||
width: height
|
width: height
|
||||||
name: "../images/battery/battery-010.svg"
|
name: "../images/battery/battery-010.svg"
|
||||||
visible: root.batteryCritical
|
visible: root.setupStatus == Thing.ThingSetupStatusComplete && root.batteryCritical
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,8 +41,7 @@ RowLayout {
|
|||||||
property Thing thing: null
|
property Thing thing: null
|
||||||
property int iconSize: app.iconSize * 1.5
|
property int iconSize: app.iconSize * 1.5
|
||||||
|
|
||||||
readonly property StateType playbackStateType: thing ? thing.thingClass.stateTypes.findByName("playbackStatus") : null
|
readonly property State playbackState: thing.stateByName("playbackStatus")
|
||||||
readonly property State playbackState: playbackStateType ? thing.states.getState(playbackStateType.id) : null
|
|
||||||
|
|
||||||
function executeAction(actionName, params) {
|
function executeAction(actionName, params) {
|
||||||
if (params === undefined) {
|
if (params === undefined) {
|
||||||
@ -58,7 +57,7 @@ RowLayout {
|
|||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
imageSource: "../images/media-skip-backward.svg"
|
imageSource: "../images/media-skip-backward.svg"
|
||||||
longpressImageSource: "../images/media-seek-backward.svg"
|
longpressImageSource: "../images/media-seek-backward.svg"
|
||||||
enabled: root.playbackState.value !== "Stopped"
|
enabled: root.playbackState && root.playbackState.value !== "Stopped"
|
||||||
opacity: enabled ? 1 : .5
|
opacity: enabled ? 1 : .5
|
||||||
|
|
||||||
repeat: true
|
repeat: true
|
||||||
@ -75,7 +74,7 @@ RowLayout {
|
|||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
imageSource: root.playbackState && root.playbackState.value === "Playing" ? "../images/media-playback-pause.svg" : "../images/media-playback-start.svg"
|
imageSource: root.playbackState && root.playbackState.value === "Playing" ? "../images/media-playback-pause.svg" : "../images/media-playback-start.svg"
|
||||||
longpressImageSource: "../images/media-playback-stop.svg"
|
longpressImageSource: "../images/media-playback-stop.svg"
|
||||||
longpressEnabled: root.playbackState.value !== "Stopped"
|
longpressEnabled: root.playbackState && root.playbackState.value !== "Stopped"
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.playbackState.value === "Playing") {
|
if (root.playbackState.value === "Playing") {
|
||||||
@ -95,7 +94,7 @@ RowLayout {
|
|||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
imageSource: "../images/media-skip-forward.svg"
|
imageSource: "../images/media-skip-forward.svg"
|
||||||
longpressImageSource: "../images/media-seek-forward.svg"
|
longpressImageSource: "../images/media-seek-forward.svg"
|
||||||
enabled: root.playbackState.value !== "Stopped"
|
enabled: root.playbackState && root.playbackState.value !== "Stopped"
|
||||||
opacity: enabled ? 1 : .5
|
opacity: enabled ? 1 : .5
|
||||||
repeat: true
|
repeat: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
|||||||
16
nymea-app/ui/components/SetupStatusIcon.qml
Normal file
16
nymea-app/ui/components/SetupStatusIcon.qml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import Nymea 1.0
|
||||||
|
|
||||||
|
ColorIcon {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property Thing thing: null
|
||||||
|
|
||||||
|
readonly property int setupStatus: thing.setupStatus
|
||||||
|
readonly property bool setupInProgress: setupStatus == Thing.ThingSetupStatusInProgress
|
||||||
|
readonly property bool setupFailed: setupStatus == Thing.ThingSetupStatusFailed
|
||||||
|
|
||||||
|
name: setupFailed ? "../images/dialog-warning-symbolic.svg"
|
||||||
|
: setupInProgress ? "../images/settings.svg" : "../images/tick.svg"
|
||||||
|
color: setupFailed ? "red" : keyColor
|
||||||
|
}
|
||||||
@ -41,7 +41,9 @@ MainPageTile {
|
|||||||
iconName: iface ? interfaceToIcon(iface.name) : interfaceToIcon("uncategorized")
|
iconName: iface ? interfaceToIcon(iface.name) : interfaceToIcon("uncategorized")
|
||||||
iconColor: app.accentColor
|
iconColor: app.accentColor
|
||||||
disconnected: devicesSubProxyConnectables.count > 0
|
disconnected: devicesSubProxyConnectables.count > 0
|
||||||
|
isWireless: devicesSubProxyConnectables.count > 0 && devicesSubProxyConnectables.get(0).thingClass.interfaces.indexOf("wirelessconnectable") >= 0
|
||||||
batteryCritical: devicesSubProxyBattery.count > 0
|
batteryCritical: devicesSubProxyBattery.count > 0
|
||||||
|
setupStatus: thingsSubProxySetupFailure.count > 0 ? Thing.ThingSetupStatusFailed : Thing.ThingSetupStatusComplete
|
||||||
|
|
||||||
property Interface iface: null
|
property Interface iface: null
|
||||||
property alias filterTagId: devicesProxy.filterTagId
|
property alias filterTagId: devicesProxy.filterTagId
|
||||||
@ -118,6 +120,12 @@ MainPageTile {
|
|||||||
parentProxy: devicesProxy
|
parentProxy: devicesProxy
|
||||||
filterBatteryCritical: true
|
filterBatteryCritical: true
|
||||||
}
|
}
|
||||||
|
DevicesProxy {
|
||||||
|
id: thingsSubProxySetupFailure
|
||||||
|
engine: _engine
|
||||||
|
parentProxy: devicesProxy
|
||||||
|
filterSetupFailed: true
|
||||||
|
}
|
||||||
|
|
||||||
property int currentDeviceIndex: 0
|
property int currentDeviceIndex: 0
|
||||||
readonly property Device currentDevice: devicesProxy.get(currentDeviceIndex)
|
readonly property Device currentDevice: devicesProxy.get(currentDeviceIndex)
|
||||||
|
|||||||
@ -37,22 +37,34 @@ import Nymea 1.0
|
|||||||
NymeaListItemDelegate {
|
NymeaListItemDelegate {
|
||||||
id: root
|
id: root
|
||||||
width: parent.width
|
width: parent.width
|
||||||
iconName: device && device.deviceClass ? app.interfacesToIcon(device.deviceClass.interfaces) : ""
|
iconName: thing && thing.thingClass ? app.interfacesToIcon(thing.thingClass.interfaces) : ""
|
||||||
text: device ? device.name : ""
|
text: thing ? thing.name : ""
|
||||||
progressive: true
|
progressive: true
|
||||||
secondaryIconName: batteryCritical ? "../images/battery/battery-010.svg" : ""
|
secondaryIconName: batteryCritical ? "../images/battery/battery-010.svg" : ""
|
||||||
tertiaryIconName: disconnected ? "../images/dialog-warning-symbolic.svg" : ""
|
tertiaryIconName: thing.setupStatus == Thing.ThingSetupStatusFailed
|
||||||
tertiaryIconColor: "red"
|
? "../images/dialog-warning-symbolic.svg"
|
||||||
|
: thing.setupStatus == Thing.ThingSetupStatusInProgress
|
||||||
|
? "../images/settings.svg"
|
||||||
|
: disconnected
|
||||||
|
? isWireless
|
||||||
|
? "../images/network-wifi-offline.svg" : "../images/network-wired-offline.svg"
|
||||||
|
: ""
|
||||||
|
tertiaryIconColor: thing.setupStatus == Thing.ThingSetupStatusInProgress ? iconKeyColor : "red"
|
||||||
|
|
||||||
property Device device: null
|
property Device device: null
|
||||||
|
property Thing thing: device
|
||||||
|
|
||||||
readonly property bool hasBatteryInterface: device && device.deviceClass.interfaces.indexOf("battery") > 0
|
readonly property bool hasBatteryInterface: thing && thing.thingClass.interfaces.indexOf("battery") > 0
|
||||||
readonly property StateType batteryCriticalStateType: hasBatteryInterface ? device.deviceClass.stateTypes.findByName("batteryCritical") : null
|
readonly property StateType batteryCriticalStateType: hasBatteryInterface ? thing.thingClass.stateTypes.findByName("batteryCritical") : null
|
||||||
readonly property State batteryCriticalState: batteryCriticalStateType ? device.states.getState(batteryCriticalStateType.id) : null
|
readonly property State batteryCriticalState: batteryCriticalStateType ? thing.states.getState(batteryCriticalStateType.id) : null
|
||||||
readonly property bool batteryCritical: batteryCriticalState && batteryCriticalState.value === true
|
readonly property bool batteryCritical: batteryCriticalState && batteryCriticalState.value === true
|
||||||
|
|
||||||
readonly property bool hasConnectableInterface: device && device.deviceClass.interfaces.indexOf("connectable") > 0
|
readonly property bool hasConnectableInterface: thing && thing.thingClass.interfaces.indexOf("connectable") > 0
|
||||||
readonly property StateType connectedStateType: hasConnectableInterface ? device.deviceClass.stateTypes.findByName("connected") : null
|
readonly property StateType connectedStateType: hasConnectableInterface ? thing.thingClass.stateTypes.findByName("connected") : null
|
||||||
readonly property State connectedState: connectedStateType ? device.states.getState(connectedStateType.id) : null
|
readonly property State connectedState: connectedStateType ? thing.states.getState(connectedStateType.id) : null
|
||||||
readonly property bool disconnected: connectedState && connectedState.value === false ? true : false
|
readonly property bool disconnected: connectedState && connectedState.value === false ? true : false
|
||||||
|
|
||||||
|
readonly property bool isWireless: root.thing.thingClass.interfaces.indexOf("wirelessconnectable") >= 0
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,14 +40,18 @@ MainPageTile {
|
|||||||
text: device.name.toUpperCase()
|
text: device.name.toUpperCase()
|
||||||
iconName: app.interfacesToIcon(deviceClass.interfaces)
|
iconName: app.interfacesToIcon(deviceClass.interfaces)
|
||||||
iconColor: app.accentColor
|
iconColor: app.accentColor
|
||||||
|
isWireless: deviceClass.interfaces.indexOf("wirelessconnectable") >= 0
|
||||||
batteryCritical: batteryCriticalState && batteryCriticalState.value === true
|
batteryCritical: batteryCriticalState && batteryCriticalState.value === true
|
||||||
disconnected: connectedState && connectedState.value === false
|
disconnected: connectedState && connectedState.value === false
|
||||||
|
signalStrength: signalStrengthState ? signalStrengthState.value : -1
|
||||||
|
setupStatus: device.setupStatus
|
||||||
|
|
||||||
backgroundImage: artworkState && artworkState.value.length > 0 ? artworkState.value : ""
|
backgroundImage: artworkState && artworkState.value.length > 0 ? artworkState.value : ""
|
||||||
|
|
||||||
property Device device: null
|
property Device device: null
|
||||||
readonly property DeviceClass deviceClass: device ? engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
readonly property DeviceClass deviceClass: device ? engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
||||||
readonly property State connectedState: deviceClass.interfaces.indexOf("connectable") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("connected").id) : null
|
readonly property State connectedState: deviceClass.interfaces.indexOf("connectable") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("connected").id) : null
|
||||||
|
readonly property State signalStrengthState: device.stateByName("signalStrength")
|
||||||
readonly property State batteryCriticalState: deviceClass.interfaces.indexOf("battery") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("batteryCritical").id) : null
|
readonly property State batteryCriticalState: deviceClass.interfaces.indexOf("battery") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("batteryCritical").id) : null
|
||||||
readonly property State artworkState: deviceClass.interfaces.indexOf("mediametadataprovider") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("artwork").id) : null
|
readonly property State artworkState: deviceClass.interfaces.indexOf("mediametadataprovider") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("artwork").id) : null
|
||||||
|
|
||||||
|
|||||||
@ -38,32 +38,32 @@ import "../components"
|
|||||||
Page {
|
Page {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias shownInterfaces: devicesProxyInternal.shownInterfaces
|
property alias shownInterfaces: thingsProxyInternal.shownInterfaces
|
||||||
property alias hiddenInterfaces: devicesProxyInternal.hiddenInterfaces
|
property alias hiddenInterfaces: thingsProxyInternal.hiddenInterfaces
|
||||||
property alias filterTagId: devicesProxyInternal.filterTagId
|
property alias filterTagId: thingsProxyInternal.filterTagId
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (devicesProxyInternal.count === 1) {
|
if (thingsProxyInternal.count === 1) {
|
||||||
enterPage(0, true)
|
enterPage(0, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property var devicesProxy: devicesProxyInternal
|
property var devicesProxy: thingsProxyInternal
|
||||||
|
property var thingsProxy: thingsProxyInternal
|
||||||
|
|
||||||
function enterPage(index, replace) {
|
function enterPage(index, replace) {
|
||||||
var device = devicesProxy.get(index);
|
var thing = thingsProxy.get(index);
|
||||||
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
|
||||||
var page = app.interfaceListToDevicePage(root.shownInterfaces);
|
var page = app.interfaceListToDevicePage(root.shownInterfaces);
|
||||||
// var page = "GenericDevicePage.qml";
|
// var page = "GenericDevicePage.qml";
|
||||||
if (replace) {
|
if (replace) {
|
||||||
pageStack.replace(Qt.resolvedUrl("../devicepages/" + page), {device: devicesProxy.get(index)})
|
pageStack.replace(Qt.resolvedUrl("../devicepages/" + page), {thing: thingsProxy.get(index)})
|
||||||
} else {
|
} else {
|
||||||
pageStack.push(Qt.resolvedUrl("../devicepages/" + page), {device: devicesProxy.get(index)})
|
pageStack.push(Qt.resolvedUrl("../devicepages/" + page), {thing: thingsProxy.get(index)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DevicesProxy {
|
DevicesProxy {
|
||||||
id: devicesProxyInternal
|
id: thingsProxyInternal
|
||||||
engine: _engine
|
engine: _engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,14 +64,13 @@ DeviceListPageBase {
|
|||||||
|
|
||||||
property bool inline: width > 500
|
property bool inline: width > 500
|
||||||
|
|
||||||
property Device device: devicesProxy.getDevice(model.id)
|
property Thing thing: thingsProxy.getThing(model.id)
|
||||||
property DeviceClass deviceClass: device.deviceClass
|
|
||||||
|
|
||||||
readonly property StateType playbackStateType: deviceClass.stateTypes.findByName("playbackStatus")
|
readonly property StateType playbackStateType: thing.thingClass.stateTypes.findByName("playbackStatus")
|
||||||
readonly property State playbackState: playbackStateType ? device.states.getState(playbackStateType.id) : null
|
readonly property State playbackState: thing.stateByName("playbackStatus")
|
||||||
|
|
||||||
readonly property StateType playerTypeStateType: deviceClass.stateTypes.findByName("playerType")
|
readonly property StateType playerTypeStateType: thing.thingClass.stateTypes.findByName("playerType")
|
||||||
readonly property State playerTypeState: playerTypeStateType ? device.states.getState(playerTypeStateType.id) : null
|
readonly property State playerTypeState: thing.stateByName("playerType")
|
||||||
|
|
||||||
bottomPadding: index === root.devicesProxy.count - 1 ? topPadding : 0
|
bottomPadding: index === root.devicesProxy.count - 1 ? topPadding : 0
|
||||||
contentItem: Pane {
|
contentItem: Pane {
|
||||||
@ -100,18 +99,23 @@ DeviceListPageBase {
|
|||||||
text: model.name
|
text: model.name
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
ColorIcon {
|
BatteryStatusIcon {
|
||||||
Layout.preferredHeight: app.iconSize * .5
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
name: "../images/battery/battery-020.svg"
|
thing: itemDelegate.thing
|
||||||
visible: itemDelegate.deviceClass.interfaces.indexOf("battery") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("batteryCritical").id).value === true
|
visible: itemDelegate.thing.setupStatus == Thing.ThingSetupStatusComplete && (hasBatteryLevel || isCritical)
|
||||||
}
|
}
|
||||||
ColorIcon {
|
ConnectionStatusIcon {
|
||||||
Layout.preferredHeight: app.iconSize * .5
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
name: "../images/dialog-warning-symbolic.svg"
|
thing: itemDelegate.thing
|
||||||
visible: itemDelegate.deviceClass.interfaces.indexOf("connectable") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("connected").id).value === false
|
visible: itemDelegate.thing.setupStatus == Thing.ThingSetupStatusComplete && (hasSignalStrength || !isConnected)
|
||||||
color: "red"
|
}
|
||||||
|
SetupStatusIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
thing: itemDelegate.thing
|
||||||
|
visible: setupFailed || setupInProgress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,28 +128,28 @@ DeviceListPageBase {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: itemDelegate.playbackState.value === "Stopped" ?
|
text: itemDelegate.playbackState.value === "Stopped" ?
|
||||||
qsTr("No playback")
|
qsTr("No playback")
|
||||||
: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("title").id).value
|
: itemDelegate.thing.stateByName("title").value
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
// font.pixelSize: app.largeFont
|
// font.pixelSize: app.largeFont
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("artist").id).value
|
text: itemDelegate.thing.stateByName("artist").value
|
||||||
font.pixelSize: app.smallFont
|
font.pixelSize: app.smallFont
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("collection").id).value
|
text: itemDelegate.thing.stateByName("collection").value
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
font.pixelSize: app.smallFont
|
font.pixelSize: app.smallFont
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
MediaControls {
|
MediaControls {
|
||||||
visible: itemDelegate.deviceClass.interfaces.indexOf("mediacontroller") >= 0
|
visible: itemDelegate.thing.thingClass.interfaces.indexOf("mediacontroller") >= 0
|
||||||
thing: itemDelegate.device
|
thing: itemDelegate.thing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
Item {
|
||||||
@ -159,8 +163,7 @@ DeviceListPageBase {
|
|||||||
id: artworkImage
|
id: artworkImage
|
||||||
width: artworkImage.sourceSize.width * height / artworkImage.sourceSize.height
|
width: artworkImage.sourceSize.width * height / artworkImage.sourceSize.height
|
||||||
anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
|
anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
|
||||||
readonly property StateType artworkStateType: device ? device.deviceClass.stateTypes.findByName("artwork") : null
|
readonly property State artworkState: thing.stateByName("artwork")
|
||||||
readonly property State artworkState: artworkStateType ? device.states.getState(artworkStateType.id) : null
|
|
||||||
source: artworkState ? artworkState.value : ""
|
source: artworkState ? artworkState.value : ""
|
||||||
}
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@ -45,7 +45,7 @@ DeviceListPageBase {
|
|||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
model: root.devicesProxy
|
model: root.thingsProxy
|
||||||
|
|
||||||
delegate: ItemDelegate {
|
delegate: ItemDelegate {
|
||||||
id: itemDelegate
|
id: itemDelegate
|
||||||
@ -53,8 +53,7 @@ DeviceListPageBase {
|
|||||||
|
|
||||||
property bool inline: width > 500
|
property bool inline: width > 500
|
||||||
|
|
||||||
property Device device: devicesProxy.getDevice(model.id)
|
property Thing thing: thingsProxy.getThing(model.id)
|
||||||
property DeviceClass deviceClass: device.deviceClass
|
|
||||||
|
|
||||||
bottomPadding: index === ListView.view.count - 1 ? topPadding : 0
|
bottomPadding: index === ListView.view.count - 1 ? topPadding : 0
|
||||||
contentItem: Pane {
|
contentItem: Pane {
|
||||||
@ -82,21 +81,25 @@ DeviceListPageBase {
|
|||||||
text: model.name
|
text: model.name
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
ColorIcon {
|
BatteryStatusIcon {
|
||||||
Layout.preferredHeight: app.iconSize * .5
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
name: "../images/battery/battery-020.svg"
|
thing: itemDelegate.thing
|
||||||
visible: itemDelegate.deviceClass.interfaces.indexOf("battery") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("batteryCritical").id).value === true
|
visible: itemDelegate.thing.setupStatus == Thing.ThingSetupStatusComplete && (hasBatteryLevel || isCritical)
|
||||||
}
|
}
|
||||||
ColorIcon {
|
ConnectionStatusIcon {
|
||||||
Layout.preferredHeight: app.iconSize * .5
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
name: "../images/dialog-warning-symbolic.svg"
|
thing: itemDelegate.thing
|
||||||
visible: itemDelegate.deviceClass.interfaces.indexOf("connectable") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("connected").id).value === false
|
visible: itemDelegate.thing.setupStatus == Thing.ThingSetupStatusComplete && (isWireless || !isConnected)
|
||||||
color: "red"
|
}
|
||||||
|
SetupStatusIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
thing: itemDelegate.thing
|
||||||
|
visible: setupFailed || setupInProgress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
GridLayout {
|
GridLayout {
|
||||||
id: dataGrid
|
id: dataGrid
|
||||||
@ -121,11 +124,11 @@ DeviceListPageBase {
|
|||||||
|
|
||||||
delegate: RowLayout {
|
delegate: RowLayout {
|
||||||
id: sensorValueDelegate
|
id: sensorValueDelegate
|
||||||
visible: itemDelegate.deviceClass.interfaces.indexOf(model.interfaceName) >= 0
|
visible: itemDelegate.thing.thingClass.interfaces.indexOf(model.interfaceName) >= 0
|
||||||
Layout.preferredWidth: contentItem.width / dataGrid.columns
|
Layout.preferredWidth: contentItem.width / dataGrid.columns
|
||||||
|
|
||||||
property StateType stateType: itemDelegate.deviceClass.stateTypes.findByName(model.stateName)
|
property StateType stateType: itemDelegate.thing.thingClass.stateTypes.findByName(model.stateName)
|
||||||
property State stateValue: stateType ? itemDelegate.device.states.getState(stateType.id) : null
|
property State stateValue: stateType ? itemDelegate.thing.states.getState(stateType.id) : null
|
||||||
|
|
||||||
ColorIcon {
|
ColorIcon {
|
||||||
Layout.preferredHeight: app.iconSize * .8
|
Layout.preferredHeight: app.iconSize * .8
|
||||||
|
|||||||
@ -53,8 +53,7 @@ DeviceListPageBase {
|
|||||||
|
|
||||||
property bool inline: width > 500
|
property bool inline: width > 500
|
||||||
|
|
||||||
property Device device: devicesProxy.getDevice(model.id)
|
property Thing thing: thingsProxy.getThing(model.id)
|
||||||
property DeviceClass deviceClass: device.deviceClass
|
|
||||||
|
|
||||||
bottomPadding: index === ListView.view.count - 1 ? topPadding : 0
|
bottomPadding: index === ListView.view.count - 1 ? topPadding : 0
|
||||||
contentItem: Pane {
|
contentItem: Pane {
|
||||||
@ -82,18 +81,23 @@ DeviceListPageBase {
|
|||||||
text: model.name
|
text: model.name
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
ColorIcon {
|
BatteryStatusIcon {
|
||||||
Layout.preferredHeight: app.iconSize * .5
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
name: "../images/battery/battery-020.svg"
|
thing: itemDelegate.thing
|
||||||
visible: itemDelegate.deviceClass.interfaces.indexOf("battery") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("batteryCritical").id).value === true
|
visible: thing.setupStatus == Thing.ThingSetupStatusComplete && (isCritical || hasBatteryLevel)
|
||||||
}
|
}
|
||||||
ColorIcon {
|
ConnectionStatusIcon {
|
||||||
Layout.preferredHeight: app.iconSize * .5
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
name: "../images/dialog-warning-symbolic.svg"
|
thing: itemDelegate.thing
|
||||||
visible: itemDelegate.deviceClass.interfaces.indexOf("connectable") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("connected").id).value === false
|
visible: thing.setupStatus == Thing.ThingSetupStatusComplete && (isWireless || !isConnected)
|
||||||
color: "red"
|
}
|
||||||
|
SetupStatusIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
thing: itemDelegate.thing
|
||||||
|
visible: setupFailed || setupInProgress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,18 +109,18 @@ DeviceListPageBase {
|
|||||||
Repeater {
|
Repeater {
|
||||||
model: ListModel {
|
model: ListModel {
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (itemDelegate.deviceClass.interfaces.indexOf("smartmeterproducer") >= 0) {
|
if (itemDelegate.thing.thingClass.interfaces.indexOf("smartmeterproducer") >= 0) {
|
||||||
append( {interfaceName: "smartmeterproducer", stateName: "totalEnergyProduced" })
|
append( {interfaceName: "smartmeterproducer", stateName: "totalEnergyProduced" })
|
||||||
}
|
}
|
||||||
if (itemDelegate.deviceClass.interfaces.indexOf("smartmeterconsumer") >= 0) {
|
if (itemDelegate.thing.thingClass.interfaces.indexOf("smartmeterconsumer") >= 0) {
|
||||||
append( {interfaceName: "smartmeterconsumer", stateName: "totalEnergyConsumed" })
|
append( {interfaceName: "smartmeterconsumer", stateName: "totalEnergyConsumed" })
|
||||||
}
|
}
|
||||||
var added = false;
|
var added = false;
|
||||||
if (itemDelegate.deviceClass.interfaces.indexOf("extendedsmartmeterproducer") >= 0) {
|
if (itemDelegate.thing.thingClass.interfaces.indexOf("extendedsmartmeterproducer") >= 0) {
|
||||||
append({interfaceName: "extendedsmartmeterconsumer", stateName: "currentPower"});
|
append({interfaceName: "extendedsmartmeterconsumer", stateName: "currentPower"});
|
||||||
added = true;
|
added = true;
|
||||||
}
|
}
|
||||||
if (!added && itemDelegate.deviceClass.interfaces.indexOf("extendedsmartmeterconsumer") >= 0) {
|
if (!added && itemDelegate.thing.thingClass.interfaces.indexOf("extendedsmartmeterconsumer") >= 0) {
|
||||||
append({interfaceName: "extendedsmartmeterconsumer", stateName: "currentPower"});
|
append({interfaceName: "extendedsmartmeterconsumer", stateName: "currentPower"});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,8 +130,8 @@ DeviceListPageBase {
|
|||||||
id: sensorValueDelegate
|
id: sensorValueDelegate
|
||||||
Layout.preferredWidth: contentItem.width / dataGrid.columns
|
Layout.preferredWidth: contentItem.width / dataGrid.columns
|
||||||
|
|
||||||
property var stateType: itemDelegate.deviceClass.stateTypes.findByName(model.stateName)
|
property StateType stateType: itemDelegate.thing.thingClass.stateTypes.findByName(model.stateName)
|
||||||
property var stateValue: stateType ? itemDelegate.device.states.getState(stateType.id) : null
|
property State stateValue: stateType ? itemDelegate.thing.states.getState(stateType.id) : null
|
||||||
|
|
||||||
ColorIcon {
|
ColorIcon {
|
||||||
Layout.preferredHeight: app.iconSize * .8
|
Layout.preferredHeight: app.iconSize * .8
|
||||||
|
|||||||
@ -36,10 +36,11 @@ import "../components"
|
|||||||
|
|
||||||
Page {
|
Page {
|
||||||
id: root
|
id: root
|
||||||
property Device device: null
|
property Thing thing: null
|
||||||
readonly property DeviceClass deviceClass: device.deviceClass
|
readonly property ThingClass thingClass: thing.thingClass
|
||||||
|
|
||||||
readonly property Device thing: device
|
property alias device: root.thing
|
||||||
|
property alias deviceClass: root.thingClass
|
||||||
|
|
||||||
property bool showLogsButton: true
|
property bool showLogsButton: true
|
||||||
property bool showDetailsButton: true
|
property bool showDetailsButton: true
|
||||||
@ -51,7 +52,7 @@ Page {
|
|||||||
signal backPressed()
|
signal backPressed()
|
||||||
|
|
||||||
header: NymeaHeader {
|
header: NymeaHeader {
|
||||||
text: device.name
|
text: root.thing.name
|
||||||
onBackPressed: {
|
onBackPressed: {
|
||||||
root.backPressed();
|
root.backPressed();
|
||||||
if (root.popStackOnBackButton) {
|
if (root.popStackOnBackButton) {
|
||||||
@ -61,7 +62,7 @@ Page {
|
|||||||
|
|
||||||
HeaderButton {
|
HeaderButton {
|
||||||
imageSource: "../images/folder-symbolic.svg"
|
imageSource: "../images/folder-symbolic.svg"
|
||||||
visible: root.deviceClass.browsable && root.showBrowserButton
|
visible: root.thingClass.browsable && root.showBrowserButton
|
||||||
onClicked: {
|
onClicked: {
|
||||||
pageStack.push(Qt.resolvedUrl("DeviceBrowserPage.qml"), {device: root.device})
|
pageStack.push(Qt.resolvedUrl("DeviceBrowserPage.qml"), {device: root.device})
|
||||||
}
|
}
|
||||||
@ -229,11 +230,11 @@ Page {
|
|||||||
visible: setupInProgress || setupFailure || batteryState !== null || (connectedState !== null && connectedState.value === false)
|
visible: setupInProgress || setupFailure || batteryState !== null || (connectedState !== null && connectedState.value === false)
|
||||||
height: visible ? contentRow.implicitHeight : 0
|
height: visible ? contentRow.implicitHeight : 0
|
||||||
anchors { left: parent.left; top: parent.top; right: parent.right }
|
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||||
property bool setupInProgress: device.setupStatus == Device.DeviceSetupStatusInProgress
|
property bool setupInProgress: root.thing.setupStatus == Thing.ThingSetupStatusInProgress
|
||||||
property bool setupFailure: device.setupStatus == Device.DeviceSetupStatusFailed
|
property bool setupFailure: root.thing.setupStatus == Thing.ThingSetupStatusFailed
|
||||||
property var batteryState: deviceClass.interfaces.indexOf("battery") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("batteryLevel").id) : null
|
property State batteryState: root.thing.stateByName("batteryLevel")
|
||||||
property var batteryCriticalState: deviceClass.interfaces.indexOf("battery") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("batteryCritical").id) : null
|
property State batteryCriticalState: root.thing.stateByName("batteryCritical")
|
||||||
property var connectedState: deviceClass.interfaces.indexOf("connectable") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("connected").id) : null
|
property State connectedState: root.thing.stateByName("connected")
|
||||||
property bool alertState: setupFailure ||
|
property bool alertState: setupFailure ||
|
||||||
(connectedState !== null && connectedState.value === false) ||
|
(connectedState !== null && connectedState.value === false) ||
|
||||||
(batteryCriticalState !== null && batteryCriticalState.value === true)
|
(batteryCriticalState !== null && batteryCriticalState.value === true)
|
||||||
@ -261,22 +262,28 @@ Page {
|
|||||||
color: "white"
|
color: "white"
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorIcon {
|
BatteryStatusIcon {
|
||||||
height: app.iconSize / 2
|
|
||||||
width: height
|
|
||||||
visible: infoPane.setupInProgress || infoPane.setupFailure || (infoPane.connectedState !== null && infoPane.connectedState.value === false)
|
|
||||||
color: "white"
|
|
||||||
name: infoPane.setupInProgress ?
|
|
||||||
"../images/settings.svg"
|
|
||||||
: "../images/dialog-warning-symbolic.svg"
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorIcon {
|
|
||||||
height: app.iconSize / 2
|
height: app.iconSize / 2
|
||||||
width: height * 1.23
|
width: height * 1.23
|
||||||
name: infoPane.batteryState !== null ? "../images/battery/battery-" + ("00" + (Math.floor(infoPane.batteryState.value / 10) * 10)).slice(-3) + ".svg" : ""
|
thing: root.thing
|
||||||
visible: infoPane.batteryState !== null
|
|
||||||
color: infoPane.alertState ? "white" : keyColor
|
color: infoPane.alertState ? "white" : keyColor
|
||||||
|
visible: thing.setupStatus == Thing.ThingSetupStatusComplete && (hasBatteryLevel || isCritical)
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectionStatusIcon {
|
||||||
|
height: app.iconSize / 2
|
||||||
|
width: height
|
||||||
|
thing: root.thing
|
||||||
|
color: infoPane.alertState ? "white" : keyColor
|
||||||
|
visible: thing.setupStatus == Thing.ThingSetupStatusComplete && (hasSignalStrength || !isConnected)
|
||||||
|
}
|
||||||
|
|
||||||
|
SetupStatusIcon {
|
||||||
|
height: app.iconSize / 2
|
||||||
|
width: height
|
||||||
|
thing: root.thing
|
||||||
|
color: infoPane.alertState ? "white" : keyColor
|
||||||
|
visible: setupFailed || setupInProgress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
nymea-app/ui/utils/NymeaUtils.qml
Normal file
18
nymea-app/ui/utils/NymeaUtils.qml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
pragma Singleton
|
||||||
|
import QtQuick 2.9
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
function pad(num, size) {
|
||||||
|
var trimmedNum = Math.floor(num)
|
||||||
|
var decimals = num - trimmedNum
|
||||||
|
var trimmedStr = "" + trimmedNum
|
||||||
|
var str = "000000000" + trimmedNum;
|
||||||
|
str = str.substr(str.length - Math.max(size, trimmedStr.length));
|
||||||
|
if (decimals !== 0) {
|
||||||
|
str += "." + (num - trimmedNum);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user