Merge remote-tracking branch 'origin/inline-warnings' into landing-silo

This commit is contained in:
Jenkins 2018-07-19 00:43:36 +02:00
commit bb49c6da91
13 changed files with 193 additions and 26 deletions

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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;

View File

@ -113,7 +113,12 @@ void RuleManager::handleRulesNotification(const QVariantMap &params)
m_rules->remove(ruleId);
m_rules->insert(parseRule(ruleMap));
} else if (params.value("notification").toString() == "Rules.RuleActiveChanged") {
m_rules->getRule(params.value("params").toMap().value("ruleId").toUuid())->setActive(params.value("params").toMap().value("active").toBool());
Rule *rule = m_rules->getRule(params.value("params").toMap().value("ruleId").toUuid());
if (rule) {
qWarning() << "Got a rule active notification for a rule we don't know";
return;
}
rule->setActive(params.value("params").toMap().value("active").toBool());
} else {
qWarning() << "Unhandled rule notification" << params;
}
@ -222,7 +227,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);
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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)})

View File

@ -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";
}

View File

@ -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

View File

@ -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: ""
}

View File

@ -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)
}

View File

@ -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 }

View File

@ -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: {