add inline warnings on tiles when things are disconnected or running out of battery
This commit is contained in:
parent
f6f867b0c9
commit
4e0e1012b6
@ -102,6 +102,11 @@ void Devices::addDevice(Device *device)
|
||||
if (idx < 0) return;
|
||||
emit dataChanged(index(idx), index(idx), {RoleSetupComplete});
|
||||
});
|
||||
connect(device->states(), &States::dataChanged, this, [device, this]() {
|
||||
int idx = m_devices.indexOf(device);
|
||||
if (idx < 0) return;
|
||||
emit dataChanged(index(idx), index(idx));
|
||||
});
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
|
||||
@ -30,19 +30,23 @@ DevicesProxy::DevicesProxy(QObject *parent) :
|
||||
connect(Engine::instance()->tagsManager()->tags(), &Tags::countChanged, this, &DevicesProxy::invalidateFilter);
|
||||
}
|
||||
|
||||
Devices *DevicesProxy::devices() const
|
||||
QAbstractItemModel *DevicesProxy::devices() const
|
||||
{
|
||||
return m_devices;
|
||||
}
|
||||
|
||||
void DevicesProxy::setDevices(Devices *devices)
|
||||
void DevicesProxy::setDevices(QAbstractItemModel *devices)
|
||||
{
|
||||
if (m_devices != devices) {
|
||||
m_devices = devices;
|
||||
setSourceModel(devices);
|
||||
setSortRole(Devices::RoleName);
|
||||
sort(0);
|
||||
connect(devices, &Devices::countChanged, this, &DevicesProxy::countChanged);
|
||||
connect(devices, SIGNAL(countChanged()), this, SIGNAL(countChanged()));
|
||||
connect(devices, &QAbstractItemModel::dataChanged, this, [this]() {
|
||||
invalidateFilter();
|
||||
emit countChanged();
|
||||
});
|
||||
emit devicesChanged();
|
||||
emit countChanged();
|
||||
}
|
||||
@ -93,9 +97,52 @@ void DevicesProxy::setHiddenInterfaces(const QStringList &hiddenInterfaces)
|
||||
}
|
||||
}
|
||||
|
||||
bool DevicesProxy::filterBatteryCritical() const
|
||||
{
|
||||
return m_filterBatteryCritical;
|
||||
}
|
||||
|
||||
void DevicesProxy::setFilterBatteryCritical(bool filterBatteryCritical)
|
||||
{
|
||||
if (m_filterBatteryCritical != filterBatteryCritical) {
|
||||
m_filterBatteryCritical = filterBatteryCritical;
|
||||
emit filterBatteryCriticalChanged();
|
||||
invalidateFilter();
|
||||
emit countChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool DevicesProxy::filterDisconnected() const
|
||||
{
|
||||
return m_filterDisconnected;
|
||||
}
|
||||
|
||||
void DevicesProxy::setFilterDisconnected(bool filterDisconnected)
|
||||
{
|
||||
if (m_filterDisconnected != filterDisconnected) {
|
||||
m_filterDisconnected = filterDisconnected;
|
||||
emit filterDisconnectedChanged();
|
||||
invalidateFilter();
|
||||
emit countChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Device *DevicesProxy::get(int index) const
|
||||
{
|
||||
return m_devices->get(mapToSource(this->index(index, 0)).row());
|
||||
return getInternal(mapToSource(this->index(index, 0)).row());
|
||||
}
|
||||
|
||||
Device *DevicesProxy::getInternal(int source_index) const
|
||||
{
|
||||
Devices* d = qobject_cast<Devices*>(m_devices);
|
||||
if (d) {
|
||||
return d->get(source_index);
|
||||
}
|
||||
DevicesProxy *dp = qobject_cast<DevicesProxy*>(m_devices);
|
||||
if (dp) {
|
||||
return dp->get(source_index);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool DevicesProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
@ -108,17 +155,17 @@ bool DevicesProxy::lessThan(const QModelIndex &left, const QModelIndex &right) c
|
||||
|
||||
bool DevicesProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
Device *device = m_devices->get(source_row);
|
||||
Device *device = getInternal(source_row);
|
||||
if (!m_filterTagId.isEmpty()) {
|
||||
if (!Engine::instance()->tagsManager()->tags()->findDeviceTag(device->id().toString(), m_filterTagId)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
DeviceClass *deviceClass = Engine::instance()->deviceManager()->deviceClasses()->getDeviceClass(device->deviceClassId());
|
||||
if (!m_shownInterfaces.isEmpty()) {
|
||||
QStringList interfaces = Engine::instance()->deviceManager()->deviceClasses()->getDeviceClass(m_devices->get(source_row)->deviceClassId())->interfaces();
|
||||
bool foundMatch = false;
|
||||
foreach (const QString &filterInterface, m_shownInterfaces) {
|
||||
if (interfaces.contains(filterInterface)) {
|
||||
if (deviceClass->interfaces().contains(filterInterface)) {
|
||||
foundMatch = true;
|
||||
continue;
|
||||
}
|
||||
@ -129,12 +176,23 @@ bool DevicesProxy::filterAcceptsRow(int source_row, const QModelIndex &source_pa
|
||||
}
|
||||
|
||||
if (!m_hiddenInterfaces.isEmpty()) {
|
||||
QStringList interfaces = Engine::instance()->deviceManager()->deviceClasses()->getDeviceClass(m_devices->get(source_row)->deviceClassId())->interfaces();
|
||||
foreach (const QString &filterInterface, m_hiddenInterfaces) {
|
||||
if (interfaces.contains(filterInterface)) {
|
||||
if (deviceClass->interfaces().contains(filterInterface)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_filterBatteryCritical) {
|
||||
if (!deviceClass->interfaces().contains("battery") || device->stateValue(deviceClass->stateTypes()->findByName("batteryCritical")->id()).toBool() == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_filterDisconnected) {
|
||||
if (!deviceClass->interfaces().contains("connectable") || device->stateValue(deviceClass->stateTypes()->findByName("connected")->id()).toBool() == true) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||
}
|
||||
|
||||
@ -33,16 +33,22 @@ class DevicesProxy : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||
Q_PROPERTY(Devices *devices READ devices WRITE setDevices NOTIFY devicesChanged)
|
||||
Q_PROPERTY(QAbstractItemModel *devices READ devices WRITE setDevices NOTIFY devicesChanged)
|
||||
Q_PROPERTY(QString filterTagId READ filterTagId WRITE setFilterTagId NOTIFY filterTagIdChanged)
|
||||
Q_PROPERTY(QStringList shownInterfaces READ shownInterfaces WRITE setShownInterfaces NOTIFY shownInterfacesChanged)
|
||||
Q_PROPERTY(QStringList hiddenInterfaces READ hiddenInterfaces WRITE setHiddenInterfaces NOTIFY hiddenInterfacesChanged)
|
||||
|
||||
// Setting this to true will imply filtering for "battery" interface
|
||||
Q_PROPERTY(bool filterBatteryCritical READ filterBatteryCritical WRITE setFilterBatteryCritical NOTIFY filterBatteryCriticalChanged)
|
||||
|
||||
// Setting this to true will imply filtering for "connectable" interface
|
||||
Q_PROPERTY(bool filterDisconnected READ filterDisconnected WRITE setFilterDisconnected NOTIFY filterDisconnectedChanged)
|
||||
|
||||
public:
|
||||
explicit DevicesProxy(QObject *parent = 0);
|
||||
|
||||
Devices *devices() const;
|
||||
void setDevices(Devices *devices);
|
||||
QAbstractItemModel *devices() const;
|
||||
void setDevices(QAbstractItemModel *devices);
|
||||
|
||||
QString filterTagId() const;
|
||||
void setFilterTagId(const QString &filterTag);
|
||||
@ -53,6 +59,12 @@ public:
|
||||
QStringList hiddenInterfaces() const;
|
||||
void setHiddenInterfaces(const QStringList &hiddenInterfaces);
|
||||
|
||||
bool filterBatteryCritical() const;
|
||||
void setFilterBatteryCritical(bool filterBatteryCritical);
|
||||
|
||||
bool filterDisconnected() const;
|
||||
void setFilterDisconnected(bool filterDisconnected);
|
||||
|
||||
Q_INVOKABLE Device *get(int index) const;
|
||||
|
||||
signals:
|
||||
@ -60,14 +72,21 @@ signals:
|
||||
void filterTagIdChanged();
|
||||
void shownInterfacesChanged();
|
||||
void hiddenInterfacesChanged();
|
||||
void filterBatteryCriticalChanged();
|
||||
void filterDisconnectedChanged();
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
Devices *m_devices = nullptr;
|
||||
Device *getInternal(int source_index) const;
|
||||
|
||||
QAbstractItemModel *m_devices = nullptr;
|
||||
QString m_filterTagId;
|
||||
QStringList m_shownInterfaces;
|
||||
QStringList m_hiddenInterfaces;
|
||||
|
||||
bool m_filterBatteryCritical = false;
|
||||
bool m_filterDisconnected = false;
|
||||
|
||||
protected:
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE;
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
||||
|
||||
@ -222,7 +222,7 @@ void RuleManager::parseEventDescriptors(const QVariantList &eventDescriptorList,
|
||||
paramDescriptor->setOperatorType((ParamDescriptor::ValueOperator)operatorEnum.keyToValue(paramDescriptorVariant.toMap().value("operator").toString().toLocal8Bit()));
|
||||
eventDescriptor->paramDescriptors()->addParamDescriptor(paramDescriptor);
|
||||
}
|
||||
qDebug() << "Adding eventdescriptor" << eventDescriptor->deviceId() << eventDescriptor->eventTypeId();
|
||||
// qDebug() << "Adding eventdescriptor" << eventDescriptor->deviceId() << eventDescriptor->eventTypeId();
|
||||
rule->eventDescriptors()->addEventDescriptor(eventDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,6 +145,6 @@ void TagsManager::addTagInternal(const QVariantMap &tagMap)
|
||||
tag->deleteLater();
|
||||
return;
|
||||
}
|
||||
qDebug() << "adding tag" << tag->tagId() << tag->value();
|
||||
// qDebug() << "adding tag" << tag->tagId() << tag->value();
|
||||
m_tags->addTag(tag);
|
||||
}
|
||||
|
||||
@ -79,6 +79,11 @@ void States::addState(State *state)
|
||||
beginInsertRows(QModelIndex(), m_states.count(), m_states.count());
|
||||
//qDebug() << "States: loaded state" << state->stateTypeId();
|
||||
m_states.append(state);
|
||||
connect(state, &State::valueChanged, this, [state, this]() {
|
||||
int idx = m_states.indexOf(state);
|
||||
if (idx < 0) return;
|
||||
emit dataChanged(index(idx), index(idx), {ValueRole});
|
||||
});
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
|
||||
@ -49,8 +49,7 @@ Page {
|
||||
anchors.fill: parent
|
||||
model: Engine.deviceManager.devices
|
||||
delegate: ThingDelegate {
|
||||
interfaces:model.interfaces
|
||||
name: model.name
|
||||
device: Engine.deviceManager.devices.get(index)
|
||||
canDelete: true
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("devicepages/ConfigureThingPage.qml"), {device: Engine.deviceManager.devices.get(index)})
|
||||
|
||||
@ -160,6 +160,8 @@ ApplicationWindow {
|
||||
return qsTr("Temperature");
|
||||
case "humiditysensor":
|
||||
return qsTr("Humidity");
|
||||
case "pressuresensor":
|
||||
return qsTr("Pressure");
|
||||
case "inputtrigger":
|
||||
return qsTr("Incoming Events");
|
||||
case "outputtrigger":
|
||||
@ -208,6 +210,8 @@ ApplicationWindow {
|
||||
return Qt.resolvedUrl("images/sensors/light.svg")
|
||||
case "conductivitysensor":
|
||||
return Qt.resolvedUrl("images/sensors/conductivity.svg")
|
||||
case "pressuresensor":
|
||||
return Qt.resolvedUrl("images/sensors/pressure.svg")
|
||||
case "media":
|
||||
case "mediacontroller":
|
||||
return Qt.resolvedUrl("images/mediaplayer-app-symbolic.svg")
|
||||
@ -265,8 +269,9 @@ ApplicationWindow {
|
||||
case "lightsensor":
|
||||
return "orange";
|
||||
case "conductivitysensor":
|
||||
return "green"
|
||||
|
||||
return "green";
|
||||
case "pressuresensor":
|
||||
return "grey";
|
||||
}
|
||||
return "grey";
|
||||
}
|
||||
|
||||
@ -13,6 +13,9 @@ SwipeDelegate {
|
||||
property int iconSize: app.iconSize
|
||||
property color iconColor: app.guhAccent
|
||||
|
||||
property bool batteryCritical: false
|
||||
property bool disconnected: false
|
||||
|
||||
signal deleteClicked()
|
||||
|
||||
contentItem: RowLayout {
|
||||
@ -51,6 +54,21 @@ SwipeDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize * .5
|
||||
Layout.preferredWidth: height
|
||||
name: "../images/battery/battery-010.svg"
|
||||
visible: root.batteryCritical
|
||||
}
|
||||
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize * .5
|
||||
Layout.preferredWidth: height
|
||||
name: "../images/dialog-warning-symbolic.svg"
|
||||
visible: root.disconnected
|
||||
color: "red"
|
||||
}
|
||||
|
||||
ColorIcon {
|
||||
Layout.preferredHeight: app.iconSize * .6
|
||||
Layout.preferredWidth: height
|
||||
|
||||
@ -2,14 +2,19 @@ import QtQuick 2.0
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.2
|
||||
import "../components"
|
||||
import Nymea 1.0
|
||||
|
||||
MeaListItemDelegate {
|
||||
id: root
|
||||
width: parent.width
|
||||
iconName: app.interfacesToIcon(root.interfaces)
|
||||
text: root.name
|
||||
iconName: deviceClass ? app.interfacesToIcon(deviceClass.interfaces) : ""
|
||||
text: device.name
|
||||
progressive: true
|
||||
batteryCritical: deviceClass && deviceClass.interfaces.indexOf("battery") >= 0 ? device.stateValue(deviceClass.stateTypes.findByName("batteryCritical").id) === true : false
|
||||
disconnected: deviceClass && deviceClass.interfaces.indexOf("connectable") >= 0 ? device.stateValue(deviceClass.stateTypes.findByName("connected").id) === false : false
|
||||
|
||||
property var device: null
|
||||
|
||||
readonly property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
||||
|
||||
property var interfaces: []
|
||||
property string name: ""
|
||||
}
|
||||
|
||||
@ -51,8 +51,7 @@ Page {
|
||||
}
|
||||
delegate: ThingDelegate {
|
||||
width: parent.width
|
||||
name: model.name
|
||||
interfaces: Engine.deviceManager.deviceClasses.getDeviceClass(model.deviceClassId).interfaces
|
||||
device: Engine.deviceManager.devices.getDevice(model.id);
|
||||
onClicked: {
|
||||
enterPage(index, false)
|
||||
}
|
||||
|
||||
@ -62,6 +62,35 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: quickAlertPane
|
||||
anchors { top: parent.top; right: parent.right; margins: app.margins }
|
||||
DevicesProxy {
|
||||
id: devicesSubProxyConnectables
|
||||
devices: devicesProxy
|
||||
filterDisconnected: true
|
||||
}
|
||||
ColorIcon {
|
||||
height: app.iconSize / 2
|
||||
width: height
|
||||
name: "../images/dialog-warning-symbolic.svg"
|
||||
color: "red"
|
||||
visible: devicesSubProxyConnectables.count > 0
|
||||
}
|
||||
DevicesProxy {
|
||||
id: devicesSubProxyBattery
|
||||
devices: devicesProxy
|
||||
filterBatteryCritical: true
|
||||
}
|
||||
ColorIcon {
|
||||
height: app.iconSize / 2
|
||||
width: height
|
||||
name: "../images/battery/battery-010.svg"
|
||||
visible: devicesSubProxyBattery.count > 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: inlineControlPane
|
||||
anchors { left: parent.left; bottom: parent.bottom; right: parent.right; margins: app.margins / 2 }
|
||||
|
||||
@ -138,6 +138,26 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: quickAlertPane
|
||||
anchors { top: parent.top; right: parent.right; margins: app.margins }
|
||||
ColorIcon {
|
||||
height: app.iconSize / 2
|
||||
width: height
|
||||
name: "../images/dialog-warning-symbolic.svg"
|
||||
color: "red"
|
||||
property var connectedState: delegateRoot.deviceClass.interfaces.indexOf("connectable") >= 0 ? delegateRoot.device.states.getState(delegateRoot.deviceClass.stateTypes.findByName("connected").id) : null
|
||||
visible: connectedState !== null && connectedState.value === false
|
||||
}
|
||||
ColorIcon {
|
||||
height: app.iconSize / 2
|
||||
width: height
|
||||
name: "../images/battery/battery-010.svg"
|
||||
property var batteryCriticalState: delegateRoot.deviceClass.interfaces.indexOf("battery") >= 0 ? delegateRoot.device.states.getState(delegateRoot.deviceClass.stateTypes.findByName("batteryCritical").id) : null
|
||||
visible: batteryCriticalState !== null && batteryCriticalState.value === true
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
|
||||
Reference in New Issue
Block a user