WIP: add support for rule templates
This commit is contained in:
parent
f5f73b4bea
commit
b8fac8dd01
@ -43,6 +43,12 @@
|
||||
#include "tagsmanager.h"
|
||||
#include "models/tagsproxymodel.h"
|
||||
#include "types/tag.h"
|
||||
#include "ruletemplates/ruletemplates.h"
|
||||
#include "ruletemplates/ruletemplate.h"
|
||||
#include "ruletemplates/eventdescriptortemplate.h"
|
||||
#include "ruletemplates/stateevaluatortemplate.h"
|
||||
#include "ruletemplates/statedescriptortemplate.h"
|
||||
#include "ruletemplates/ruleactiontemplate.h"
|
||||
|
||||
static QObject* interfacesModel_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
|
||||
{
|
||||
@ -162,6 +168,15 @@ void registerQmlTypes() {
|
||||
qmlRegisterUncreatableType<WirelessAccessPoints>(uri, 1, 0, "WirelessAccessPoints", "Can't create this in QML. Get it from the Engine instance.");
|
||||
qmlRegisterUncreatableType<WirelessAccessPointsProxy>(uri, 1, 0, "WirelessAccessPoints", "Can't create this in QML. Get it from the Engine instance.");
|
||||
|
||||
qmlRegisterType<RuleTemplates>(uri, 1, 0, "RuleTemplates");
|
||||
qmlRegisterType<RuleTemplatesFilterModel>(uri, 1, 0, "RuleTemplatesFilterModel");
|
||||
qmlRegisterUncreatableType<RuleTemplate>(uri, 1, 0, "RuleTemplate", "Get them from RuleTemplates");
|
||||
qmlRegisterUncreatableType<EventDescriptorTemplates>(uri, 1, 0, "EventDescriptorTemplates", "Get it from RuleTemplate");
|
||||
qmlRegisterUncreatableType<EventDescriptorTemplate>(uri, 1, 0, "EventDescriptorTemplate", "Get it from EventDescriptorTemplates");
|
||||
qmlRegisterUncreatableType<StateEvaluatorTemplate>(uri, 1, 0, "StateEvaluatorTemplate", "Get it from RuleTemplate");
|
||||
qmlRegisterUncreatableType<StateDescriptorTemplate>(uri, 1, 0, "StateDescriptorTemplate", "Get it from StateEvaluatorTemplate");
|
||||
qmlRegisterUncreatableType<RuleActionTemplates>(uri, 1, 0, "RuleActionTemplates", "Get it from RuleTemplate");
|
||||
qmlRegisterUncreatableType<RuleActionTemplate>(uri, 1, 0, "RuleActionTemplate", "Get it from RuleActionTemplates");
|
||||
}
|
||||
|
||||
#endif // LIBNYMEAAPPCORE_H
|
||||
|
||||
@ -61,6 +61,13 @@ SOURCES += \
|
||||
models/tagsproxymodel.cpp \
|
||||
tagsmanager.cpp \
|
||||
wifisetup/wirelessaccesspointsproxy.cpp \
|
||||
models/tagsproxymodel.cpp \
|
||||
ruletemplates/ruletemplate.cpp \
|
||||
ruletemplates/ruletemplates.cpp \
|
||||
ruletemplates/eventdescriptortemplate.cpp \
|
||||
ruletemplates/ruleactiontemplate.cpp \
|
||||
ruletemplates/stateevaluatortemplate.cpp \
|
||||
ruletemplates/statedescriptortemplate.cpp
|
||||
|
||||
HEADERS += \
|
||||
engine.h \
|
||||
@ -107,7 +114,13 @@ HEADERS += \
|
||||
models/interfacesproxy.h \
|
||||
tagsmanager.h \
|
||||
models/tagsproxymodel.h \
|
||||
wifisetup/wirelessaccesspointsproxy.h
|
||||
wifisetup/wirelessaccesspointsproxy.h \
|
||||
ruletemplates/ruletemplate.h \
|
||||
ruletemplates/ruletemplates.h \
|
||||
ruletemplates/eventdescriptortemplate.h \
|
||||
ruletemplates/ruleactiontemplate.h \
|
||||
ruletemplates/stateevaluatortemplate.h \
|
||||
ruletemplates/statedescriptortemplate.h
|
||||
|
||||
unix {
|
||||
target.path = /usr/lib
|
||||
|
||||
@ -51,7 +51,7 @@ Rules *RuleManager::rules() const
|
||||
|
||||
Rule *RuleManager::createNewRule()
|
||||
{
|
||||
return new Rule();
|
||||
return new Rule(QUuid(), this);
|
||||
}
|
||||
|
||||
void RuleManager::addRule(const QVariantMap params)
|
||||
@ -154,7 +154,7 @@ void RuleManager::getRuleDetailsReply(const QVariantMap ¶ms)
|
||||
qDebug() << "Got rule details for a rule we don't know";
|
||||
return;
|
||||
}
|
||||
// qDebug() << "got rule details for rule" << ruleMap;
|
||||
qDebug() << "got rule details for rule" << qUtf8Printable(QJsonDocument::fromVariant(ruleMap).toJson());
|
||||
parseEventDescriptors(ruleMap.value("eventDescriptors").toList(), rule);
|
||||
parseRuleActions(ruleMap.value("actions").toList(), rule);
|
||||
parseRuleExitActions(ruleMap.value("exitActions").toList(), rule);
|
||||
@ -222,6 +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();
|
||||
rule->eventDescriptors()->addEventDescriptor(eventDescriptor);
|
||||
}
|
||||
}
|
||||
@ -242,7 +243,6 @@ StateEvaluator *RuleManager::parseStateEvaluator(const QVariantMap &stateEvaluat
|
||||
} else {
|
||||
sd = new StateDescriptor(sdMap.value("interface").toString(), sdMap.value("interfaceState").toString(), op, sdMap.value("value"), stateEvaluator);
|
||||
}
|
||||
qDebug() << "Created StateDescriptor:" << sd->interfaceName() << sd->interfaceState() << sd->deviceId() << sd->stateTypeId();
|
||||
stateEvaluator->setStateDescriptor(sd);
|
||||
|
||||
foreach (const QVariant &childEvaluatorVariant, stateEvaluatorMap.value("childEvaluators").toList()) {
|
||||
|
||||
31
libnymea-app-core/ruletemplates/eventdescriptortemplate.cpp
Normal file
31
libnymea-app-core/ruletemplates/eventdescriptortemplate.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "eventdescriptortemplate.h"
|
||||
|
||||
EventDescriptorTemplate::EventDescriptorTemplate(const QString &interfaceName, const QString &interfaceEvent, int selectionId, SelectionMode selectionMode, QObject *parent):
|
||||
QObject(parent),
|
||||
m_interfaceName(interfaceName),
|
||||
m_interfaceEvent(interfaceEvent),
|
||||
m_selectionId(selectionId),
|
||||
m_selectionMode(selectionMode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString EventDescriptorTemplate::interfaceName() const
|
||||
{
|
||||
return m_interfaceName;
|
||||
}
|
||||
|
||||
QString EventDescriptorTemplate::interfaceEvent() const
|
||||
{
|
||||
return m_interfaceEvent;
|
||||
}
|
||||
|
||||
int EventDescriptorTemplate::selectionId() const
|
||||
{
|
||||
return m_selectionId;
|
||||
}
|
||||
|
||||
EventDescriptorTemplate::SelectionMode EventDescriptorTemplate::selectionMode() const
|
||||
{
|
||||
return m_selectionMode;
|
||||
}
|
||||
68
libnymea-app-core/ruletemplates/eventdescriptortemplate.h
Normal file
68
libnymea-app-core/ruletemplates/eventdescriptortemplate.h
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef EVENTDESCRIPTORTEMPLATE_H
|
||||
#define EVENTDESCRIPTORTEMPLATE_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class EventDescriptorTemplate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString interfaceName READ interfaceName CONSTANT)
|
||||
Q_PROPERTY(QString interfaceEvent READ interfaceEvent CONSTANT)
|
||||
Q_PROPERTY(int selectionId READ selectionId CONSTANT)
|
||||
Q_PROPERTY(SelectionMode selectionMode READ selectionMode CONSTANT)
|
||||
public:
|
||||
enum SelectionMode {
|
||||
SelectionModeAny,
|
||||
SelectionModeDevice,
|
||||
SelectionModeInterface,
|
||||
};
|
||||
Q_ENUM(SelectionMode)
|
||||
|
||||
explicit EventDescriptorTemplate(const QString &interfaceName, const QString &interfaceEvent, int selectionId, SelectionMode selectionMode = SelectionModeAny, QObject *parent = nullptr);
|
||||
|
||||
QString interfaceName() const;
|
||||
QString interfaceEvent() const;
|
||||
int selectionId() const;
|
||||
SelectionMode selectionMode() const;
|
||||
|
||||
private:
|
||||
QString m_interfaceName;
|
||||
QString m_interfaceEvent;
|
||||
int m_selectionId = 0;
|
||||
SelectionMode m_selectionMode = SelectionModeAny;
|
||||
};
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class EventDescriptorTemplates: public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||
public:
|
||||
EventDescriptorTemplates(QObject *parent = nullptr): QAbstractListModel(parent) {}
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override { Q_UNUSED(parent); return m_list.count(); }
|
||||
QVariant data(const QModelIndex &index, int role) const override { Q_UNUSED(index); Q_UNUSED(role); return QVariant(); }
|
||||
|
||||
void addEventDescriptorTemplate(EventDescriptorTemplate *eventDescriptorTemplate) {
|
||||
eventDescriptorTemplate->setParent(this);
|
||||
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||
m_list.append(eventDescriptorTemplate);
|
||||
endInsertRows();
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
Q_INVOKABLE EventDescriptorTemplate* get(int index) const {
|
||||
if (index < 0 || index >= m_list.count()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_list.at(index);
|
||||
}
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
QList<EventDescriptorTemplate*> m_list;
|
||||
};
|
||||
#endif // EVENTDESCRIPTORTEMPLATE_H
|
||||
38
libnymea-app-core/ruletemplates/ruleactiontemplate.cpp
Normal file
38
libnymea-app-core/ruletemplates/ruleactiontemplate.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "ruleactiontemplate.h"
|
||||
|
||||
|
||||
RuleActionTemplate::RuleActionTemplate(const QString &interfaceName, const QString &interfaceAction, int selectionId, SelectionMode selectionMode, QObject *parent):
|
||||
QObject(parent),
|
||||
m_interfaceName(interfaceName),
|
||||
m_interfaceAction(interfaceAction),
|
||||
m_selectionId(selectionId),
|
||||
m_selectionMode(selectionMode),
|
||||
m_ruleActionParams(new RuleActionParams(this))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString RuleActionTemplate::interfaceName() const
|
||||
{
|
||||
return m_interfaceName;
|
||||
}
|
||||
|
||||
QString RuleActionTemplate::interfaceAction() const
|
||||
{
|
||||
return m_interfaceAction;
|
||||
}
|
||||
|
||||
int RuleActionTemplate::selectionId() const
|
||||
{
|
||||
return m_selectionId;
|
||||
}
|
||||
|
||||
RuleActionTemplate::SelectionMode RuleActionTemplate::selectionMode() const
|
||||
{
|
||||
return m_selectionMode;
|
||||
}
|
||||
|
||||
RuleActionParams *RuleActionTemplate::ruleActionParams() const
|
||||
{
|
||||
return m_ruleActionParams;
|
||||
}
|
||||
74
libnymea-app-core/ruletemplates/ruleactiontemplate.h
Normal file
74
libnymea-app-core/ruletemplates/ruleactiontemplate.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef RULEACTIONTEMPLATE_H
|
||||
#define RULEACTIONTEMPLATE_H
|
||||
|
||||
#include "types/ruleactionparams.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class RuleActionTemplate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString interfaceName READ interfaceName CONSTANT)
|
||||
Q_PROPERTY(QString interfaceAction READ interfaceAction CONSTANT)
|
||||
Q_PROPERTY(int selectionId READ selectionId CONSTANT)
|
||||
Q_PROPERTY(SelectionMode selectionMode READ selectionMode CONSTANT)
|
||||
Q_PROPERTY(RuleActionParams* ruleActionParams READ ruleActionParams CONSTANT)
|
||||
|
||||
public:
|
||||
enum SelectionMode {
|
||||
SelectionModeAny,
|
||||
SelectionModeDevice,
|
||||
SelectionModeInterface
|
||||
};
|
||||
Q_ENUM(SelectionMode)
|
||||
|
||||
explicit RuleActionTemplate(const QString &interfaceName, const QString &interfaceAction, int selectionId, SelectionMode selectionMode = SelectionModeAny, QObject *parent = nullptr);
|
||||
|
||||
QString interfaceName() const;
|
||||
QString interfaceAction() const;
|
||||
int selectionId() const;
|
||||
SelectionMode selectionMode() const;
|
||||
RuleActionParams* ruleActionParams() const;
|
||||
|
||||
private:
|
||||
QString m_interfaceName;
|
||||
QString m_interfaceAction;
|
||||
int m_selectionId = 0;
|
||||
SelectionMode m_selectionMode = SelectionModeAny;
|
||||
RuleActionParams* m_ruleActionParams = nullptr;
|
||||
};
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class RuleActionTemplates: public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||
public:
|
||||
RuleActionTemplates(QObject *parent = nullptr): QAbstractListModel(parent) {}
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override { Q_UNUSED(parent); return m_list.count(); }
|
||||
QVariant data(const QModelIndex &index, int role) const override { Q_UNUSED(index); Q_UNUSED(role); return QVariant(); }
|
||||
|
||||
void addRuleActionTemplate(RuleActionTemplate* ruleActionTemplate) {
|
||||
ruleActionTemplate->setParent(this);
|
||||
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||
m_list.append(ruleActionTemplate);
|
||||
endInsertRows();
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
Q_INVOKABLE RuleActionTemplate* get(int index) const {
|
||||
if (index < 0 || index >= m_list.count()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_list.at(index);
|
||||
}
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
QList<RuleActionTemplate*> m_list;
|
||||
};
|
||||
|
||||
#endif // RULEACTIONTEMPLATE_H
|
||||
53
libnymea-app-core/ruletemplates/ruletemplate.cpp
Normal file
53
libnymea-app-core/ruletemplates/ruletemplate.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "ruletemplate.h"
|
||||
#include "eventdescriptortemplate.h"
|
||||
#include "stateevaluatortemplate.h"
|
||||
#include "ruleactiontemplate.h"
|
||||
|
||||
RuleTemplate::RuleTemplate(const QString &description, const QString &ruleNameTemplate, QObject *parent):
|
||||
QObject(parent),
|
||||
m_description(description),
|
||||
m_ruleNameTemplate(ruleNameTemplate),
|
||||
m_eventDescriptorTemplates(new EventDescriptorTemplates(this)),
|
||||
m_ruleActionTemplates(new RuleActionTemplates(this)),
|
||||
m_ruleExitActionTemplates(new RuleActionTemplates(this))
|
||||
{
|
||||
}
|
||||
|
||||
QString RuleTemplate::description() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
QString RuleTemplate::ruleNameTemplate() const
|
||||
{
|
||||
return m_ruleNameTemplate;
|
||||
}
|
||||
|
||||
EventDescriptorTemplates *RuleTemplate::eventDescriptorTemplates() const
|
||||
{
|
||||
return m_eventDescriptorTemplates;
|
||||
}
|
||||
|
||||
StateEvaluatorTemplate *RuleTemplate::stateEvaluatorTemplate() const
|
||||
{
|
||||
return m_stateEvaluatorTemplate;
|
||||
}
|
||||
|
||||
void RuleTemplate::setStateEvaluatorTemplate(StateEvaluatorTemplate *stateEvaluatorTemplate)
|
||||
{
|
||||
if (m_stateEvaluatorTemplate) {
|
||||
m_stateEvaluatorTemplate->deleteLater();
|
||||
}
|
||||
stateEvaluatorTemplate->setParent(this);
|
||||
m_stateEvaluatorTemplate = stateEvaluatorTemplate;
|
||||
}
|
||||
|
||||
RuleActionTemplates *RuleTemplate::ruleActionTemplates() const
|
||||
{
|
||||
return m_ruleActionTemplates;
|
||||
}
|
||||
|
||||
RuleActionTemplates *RuleTemplate::ruleExitActionTemplates() const
|
||||
{
|
||||
return m_ruleExitActionTemplates;
|
||||
}
|
||||
41
libnymea-app-core/ruletemplates/ruletemplate.h
Normal file
41
libnymea-app-core/ruletemplates/ruletemplate.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef RULETEMPLATE_H
|
||||
#define RULETEMPLATE_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class EventDescriptorTemplates;
|
||||
class RuleActionTemplates;
|
||||
class StateEvaluatorTemplate;
|
||||
|
||||
class RuleTemplate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString description READ description CONSTANT)
|
||||
Q_PROPERTY(QString ruleNameTemplate READ ruleNameTemplate CONSTANT)
|
||||
Q_PROPERTY(EventDescriptorTemplates* eventDescriptorTemplates READ eventDescriptorTemplates CONSTANT)
|
||||
Q_PROPERTY(StateEvaluatorTemplate* stateEvaluatorTemplate READ stateEvaluatorTemplate CONSTANT)
|
||||
Q_PROPERTY(RuleActionTemplates* ruleActionTemplates READ ruleActionTemplates CONSTANT)
|
||||
Q_PROPERTY(RuleActionTemplates* ruleExitActionTemplates READ ruleExitActionTemplates CONSTANT)
|
||||
|
||||
public:
|
||||
explicit RuleTemplate(const QString &description, const QString &ruleNameTemplate, QObject *parent = nullptr);
|
||||
|
||||
QString description() const;
|
||||
QString ruleNameTemplate() const;
|
||||
|
||||
EventDescriptorTemplates* eventDescriptorTemplates() const;
|
||||
StateEvaluatorTemplate* stateEvaluatorTemplate() const;
|
||||
void setStateEvaluatorTemplate(StateEvaluatorTemplate *stateEvaluatorTemplate);
|
||||
RuleActionTemplates* ruleActionTemplates() const;
|
||||
RuleActionTemplates* ruleExitActionTemplates() const;
|
||||
|
||||
private:
|
||||
QString m_description;
|
||||
QString m_ruleNameTemplate;
|
||||
EventDescriptorTemplates* m_eventDescriptorTemplates = nullptr;
|
||||
StateEvaluatorTemplate* m_stateEvaluatorTemplate = nullptr;
|
||||
RuleActionTemplates *m_ruleActionTemplates = nullptr;
|
||||
RuleActionTemplates *m_ruleExitActionTemplates = nullptr;
|
||||
};
|
||||
|
||||
#endif // RULETEMPLATE_H
|
||||
141
libnymea-app-core/ruletemplates/ruletemplates.cpp
Normal file
141
libnymea-app-core/ruletemplates/ruletemplates.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
#include "ruletemplates.h"
|
||||
|
||||
#include "ruletemplate.h"
|
||||
#include "eventdescriptortemplate.h"
|
||||
#include "ruleactiontemplate.h"
|
||||
#include "stateevaluatortemplate.h"
|
||||
|
||||
#include "types/ruleactionparam.h"
|
||||
#include "types/ruleactionparams.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
RuleTemplates::RuleTemplates(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
RuleTemplate* t;
|
||||
EventDescriptorTemplate* evt;
|
||||
StateEvaluatorTemplate* set;
|
||||
RuleActionTemplate* rat;
|
||||
RuleActionTemplate* reat; // exit
|
||||
|
||||
t = new RuleTemplate("Switch a light", "%0 switches %1", this);
|
||||
evt = new EventDescriptorTemplate("button", "pressed", 0, EventDescriptorTemplate::SelectionModeDevice);
|
||||
t->eventDescriptorTemplates()->addEventDescriptorTemplate(evt);
|
||||
set = new StateEvaluatorTemplate(new StateDescriptorTemplate("light", "power", 1, StateDescriptorTemplate::ValueOperatorEquals, false));
|
||||
t->setStateEvaluatorTemplate(set);
|
||||
rat = new RuleActionTemplate("light", "power", 1, RuleActionTemplate::SelectionModeDevice);
|
||||
rat->ruleActionParams()->setRuleActionParamByName("power", true);
|
||||
t->ruleActionTemplates()->addRuleActionTemplate(rat);
|
||||
reat = new RuleActionTemplate("light", "power", 1, RuleActionTemplate::SelectionModeDevice);
|
||||
reat->ruleActionParams()->setRuleActionParamByName("power", false);
|
||||
t->ruleExitActionTemplates()->addRuleActionTemplate(reat);
|
||||
m_list.append(t);
|
||||
|
||||
t = new RuleTemplate("Intelligent blinds", "Intelligent blinds %1", this);
|
||||
set = new StateEvaluatorTemplate(new StateDescriptorTemplate("temperaturesensor", "temperature", 0, StateDescriptorTemplate::ValueOperatorGreater, 20));
|
||||
t->setStateEvaluatorTemplate(set);
|
||||
rat = new RuleActionTemplate("simpleclosable", "close", 1, RuleActionTemplate::SelectionModeDevice);
|
||||
t->ruleActionTemplates()->addRuleActionTemplate(rat);
|
||||
reat = new RuleActionTemplate("simpleclosable", "open", 1, RuleActionTemplate::SelectionModeDevice);
|
||||
t->ruleExitActionTemplates()->addRuleActionTemplate(reat);
|
||||
m_list.append(t);
|
||||
|
||||
t = new RuleTemplate("Leave home - This will turn of everything when you press a button.", "Leave home", this);
|
||||
evt = new EventDescriptorTemplate("button", "pressed", 0, EventDescriptorTemplate::SelectionModeDevice);
|
||||
t->eventDescriptorTemplates()->addEventDescriptorTemplate(evt);
|
||||
rat = new RuleActionTemplate("power", "power", 1, RuleActionTemplate::SelectionModeInterface);
|
||||
t->ruleActionTemplates()->addRuleActionTemplate(rat);
|
||||
m_list.append(t);
|
||||
|
||||
|
||||
t = new RuleTemplate("Remind me to water my plant", "Remind me to water my %0 plant", this);
|
||||
evt = new EventDescriptorTemplate("humiditysensor", "humidity", 0, EventDescriptorTemplate::SelectionModeDevice);
|
||||
t->eventDescriptorTemplates()->addEventDescriptorTemplate(evt);
|
||||
m_list.append(t);
|
||||
|
||||
}
|
||||
|
||||
int RuleTemplates::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_list.count();
|
||||
}
|
||||
|
||||
QVariant RuleTemplates::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
switch (role) {
|
||||
case RoleDescription:
|
||||
return m_list.at(index.row())->description();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> RuleTemplates::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles.insert(RoleDescription, "description");
|
||||
return roles;
|
||||
}
|
||||
|
||||
RuleTemplate *RuleTemplates::get(int index) const
|
||||
{
|
||||
if (index < 0 || index >= m_list.count()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_list.at(index);
|
||||
}
|
||||
|
||||
bool RuleTemplatesFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
Q_UNUSED(source_parent)
|
||||
if (!m_ruleTemplates) {
|
||||
return false;
|
||||
}
|
||||
RuleTemplate *t = m_ruleTemplates->get(source_row);
|
||||
qDebug() << "---------------" << t->description() << m_filterInterfaceNames;
|
||||
if (!m_filterInterfaceNames.isEmpty()) {
|
||||
bool found = false;
|
||||
for (int i = 0; i < t->eventDescriptorTemplates()->rowCount(); i++) {
|
||||
if (m_filterInterfaceNames.contains(t->eventDescriptorTemplates()->get(i)->interfaceName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found && t->stateEvaluatorTemplate() && stateEvaluatorTemplateContainsInterface(t->stateEvaluatorTemplate(), m_filterInterfaceNames)) {
|
||||
found = true;
|
||||
}
|
||||
if (!found) {
|
||||
for (int i = 0; i < t->ruleActionTemplates()->rowCount(); i++) {
|
||||
if (m_filterInterfaceNames.contains(t->ruleActionTemplates()->get(i)->interfaceName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
for (int i = 0; i < t->ruleExitActionTemplates()->rowCount(); i++) {
|
||||
if (m_filterInterfaceNames.contains(t->ruleExitActionTemplates()->get(i)->interfaceName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuleTemplatesFilterModel::stateEvaluatorTemplateContainsInterface(StateEvaluatorTemplate *stateEvaluatorTemplate, const QStringList &interfaceNames) const
|
||||
{
|
||||
if (interfaceNames.contains(stateEvaluatorTemplate->stateDescriptorTemplate()->interfaceName())) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < stateEvaluatorTemplate->childEvaluatorTemplates()->rowCount(); i++) {
|
||||
if (stateEvaluatorTemplateContainsInterface(stateEvaluatorTemplate->childEvaluatorTemplates()->get(i), interfaceNames)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
64
libnymea-app-core/ruletemplates/ruletemplates.h
Normal file
64
libnymea-app-core/ruletemplates/ruletemplates.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef RULETEMPLATES_H
|
||||
#define RULETEMPLATES_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class RuleTemplate;
|
||||
class StateEvaluatorTemplate;
|
||||
|
||||
class RuleTemplates : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||
public:
|
||||
enum Roles {
|
||||
RoleDescription
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit RuleTemplates(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
Q_INVOKABLE RuleTemplate* get(int index) const;
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
|
||||
private:
|
||||
QList<RuleTemplate*> m_list;
|
||||
|
||||
};
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class RuleTemplatesFilterModel: public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(RuleTemplates* ruleTemplates READ ruleTemplates WRITE setRuleTemplates NOTIFY ruleTemplatesChanged)
|
||||
Q_PROPERTY(QStringList filterInterfaceNames READ filterInterfaceNames WRITE setFilterInterfaceNames NOTIFY filterInterfaceNamesChanged)
|
||||
public:
|
||||
RuleTemplatesFilterModel(QObject *parent = nullptr): QSortFilterProxyModel(parent) {}
|
||||
RuleTemplates* ruleTemplates() const { return m_ruleTemplates; }
|
||||
void setRuleTemplates(RuleTemplates* ruleTemplates) { if (m_ruleTemplates != ruleTemplates) { m_ruleTemplates = ruleTemplates; setSourceModel(ruleTemplates); emit ruleTemplatesChanged(); invalidateFilter();}}
|
||||
QStringList filterInterfaceNames() const { return m_filterInterfaceNames; }
|
||||
void setFilterInterfaceNames(const QStringList &filterInterfaceNames) { if (m_filterInterfaceNames != filterInterfaceNames) m_filterInterfaceNames = filterInterfaceNames; emit filterInterfaceNamesChanged(); invalidateFilter();}
|
||||
Q_INVOKABLE RuleTemplate* get(int index) {
|
||||
if (index < 0 || index >= rowCount()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_ruleTemplates->get(mapToSource(this->index(index, 0)).row());
|
||||
}
|
||||
protected:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
||||
bool stateEvaluatorTemplateContainsInterface(StateEvaluatorTemplate *stateEvaluatorTemplate, const QStringList &interfaceNames) const;
|
||||
signals:
|
||||
void ruleTemplatesChanged();
|
||||
void filterInterfaceNamesChanged();
|
||||
private:
|
||||
RuleTemplates* m_ruleTemplates = nullptr;
|
||||
QStringList m_filterInterfaceNames;
|
||||
};
|
||||
|
||||
#endif // RULETEMPLATES_H
|
||||
37
libnymea-app-core/ruletemplates/statedescriptortemplate.cpp
Normal file
37
libnymea-app-core/ruletemplates/statedescriptortemplate.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "statedescriptortemplate.h"
|
||||
|
||||
StateDescriptorTemplate::StateDescriptorTemplate(const QString &interfaceName, const QString &interfaceState, int selectionId, StateDescriptorTemplate::ValueOperator valueOperator, const QVariant &value, QObject *parent):
|
||||
QObject(parent),
|
||||
m_interfaceName(interfaceName),
|
||||
m_interfaceState(interfaceState),
|
||||
m_selectionId(selectionId),
|
||||
m_valueOperator(valueOperator),
|
||||
m_value(value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString StateDescriptorTemplate::interfaceName() const
|
||||
{
|
||||
return m_interfaceName;
|
||||
}
|
||||
|
||||
QString StateDescriptorTemplate::interfaceState() const
|
||||
{
|
||||
return m_interfaceState;
|
||||
}
|
||||
|
||||
int StateDescriptorTemplate::selectionId() const
|
||||
{
|
||||
return m_selectionId;
|
||||
}
|
||||
|
||||
StateDescriptorTemplate::ValueOperator StateDescriptorTemplate::valueOperator() const
|
||||
{
|
||||
return m_valueOperator;
|
||||
}
|
||||
|
||||
QVariant StateDescriptorTemplate::value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
43
libnymea-app-core/ruletemplates/statedescriptortemplate.h
Normal file
43
libnymea-app-core/ruletemplates/statedescriptortemplate.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef STATEDESCRIPTORTEMPLATE_H
|
||||
#define STATEDESCRIPTORTEMPLATE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
|
||||
class StateDescriptorTemplate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString interfaceName READ interfaceName CONSTANT)
|
||||
Q_PROPERTY(QString interfaceState READ interfaceState CONSTANT)
|
||||
Q_PROPERTY(int selectionId READ selectionId CONSTANT)
|
||||
Q_PROPERTY(ValueOperator valueOperator READ valueOperator CONSTANT)
|
||||
Q_PROPERTY(QVariant value READ value CONSTANT)
|
||||
|
||||
public:
|
||||
enum ValueOperator {
|
||||
ValueOperatorEquals,
|
||||
ValueOperatorNotEquals,
|
||||
ValueOperatorLess,
|
||||
ValueOperatorGreater,
|
||||
ValueOperatorLessOrEqual,
|
||||
ValueOperatorGreaterOrEqual
|
||||
};
|
||||
Q_ENUM(ValueOperator)
|
||||
|
||||
explicit StateDescriptorTemplate(const QString &interfaceName, const QString &interfaceState, int selectionId, ValueOperator valueOperator = ValueOperatorEquals, const QVariant &value = QVariant(), QObject *parent = nullptr);
|
||||
|
||||
QString interfaceName() const;
|
||||
QString interfaceState() const;
|
||||
int selectionId() const;
|
||||
ValueOperator valueOperator() const;
|
||||
QVariant value() const;
|
||||
|
||||
private:
|
||||
QString m_interfaceName;
|
||||
QString m_interfaceState;
|
||||
ValueOperator m_valueOperator = ValueOperatorEquals;
|
||||
QVariant m_value;
|
||||
int m_selectionId = 0;
|
||||
};
|
||||
|
||||
#endif // STATEDESCRIPTORTEMPLATE_H
|
||||
25
libnymea-app-core/ruletemplates/stateevaluatortemplate.cpp
Normal file
25
libnymea-app-core/ruletemplates/stateevaluatortemplate.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "stateevaluatortemplate.h"
|
||||
|
||||
StateEvaluatorTemplate::StateEvaluatorTemplate(StateDescriptorTemplate *stateDescriptorTemplate, StateOperator stateOperator, QObject *parent):
|
||||
QObject(parent),
|
||||
m_stateDescriptorTemplate(stateDescriptorTemplate),
|
||||
m_stateOperator(stateOperator),
|
||||
m_childEvaluatorTemplates(new StateEvaluatorTemplates(this))
|
||||
{
|
||||
stateDescriptorTemplate->setParent(this);
|
||||
}
|
||||
|
||||
StateDescriptorTemplate *StateEvaluatorTemplate::stateDescriptorTemplate() const
|
||||
{
|
||||
return m_stateDescriptorTemplate;
|
||||
}
|
||||
|
||||
StateEvaluatorTemplate::StateOperator StateEvaluatorTemplate::stateOperator() const
|
||||
{
|
||||
return m_stateOperator;
|
||||
}
|
||||
|
||||
StateEvaluatorTemplates *StateEvaluatorTemplate::childEvaluatorTemplates() const
|
||||
{
|
||||
return m_childEvaluatorTemplates;
|
||||
}
|
||||
65
libnymea-app-core/ruletemplates/stateevaluatortemplate.h
Normal file
65
libnymea-app-core/ruletemplates/stateevaluatortemplate.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef STATEEVALUATORTEMPLATE_H
|
||||
#define STATEEVALUATORTEMPLATE_H
|
||||
|
||||
#include "statedescriptortemplate.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class StateEvaluatorTemplates;
|
||||
|
||||
class StateEvaluatorTemplate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(StateDescriptorTemplate* stateDescriptorTemplate READ stateDescriptorTemplate CONSTANT)
|
||||
Q_PROPERTY(StateOperator stateOperator READ stateOperator CONSTANT)
|
||||
Q_PROPERTY(StateEvaluatorTemplates* childEvaluatorTemplates READ childEvaluatorTemplates CONSTANT)
|
||||
|
||||
public:
|
||||
enum StateOperator {
|
||||
StateOperatorAnd,
|
||||
StateOperatorOr
|
||||
};
|
||||
Q_ENUM(StateOperator)
|
||||
|
||||
explicit StateEvaluatorTemplate(StateDescriptorTemplate* stateDescriptorTemplate, StateOperator stateOperator = StateOperatorAnd, QObject *parent = nullptr);
|
||||
|
||||
StateDescriptorTemplate* stateDescriptorTemplate() const;
|
||||
StateOperator stateOperator() const;
|
||||
StateEvaluatorTemplates* childEvaluatorTemplates() const;
|
||||
|
||||
private:
|
||||
StateDescriptorTemplate* m_stateDescriptorTemplate = nullptr;
|
||||
StateOperator m_stateOperator = StateOperatorAnd;
|
||||
StateEvaluatorTemplates *m_childEvaluatorTemplates = nullptr;
|
||||
};
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class StateEvaluatorTemplates: public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ rowCount CONSTANT)
|
||||
|
||||
public:
|
||||
StateEvaluatorTemplates(QObject *parent = nullptr): QAbstractListModel(parent) {}
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override { Q_UNUSED(parent); return m_list.count(); }
|
||||
QVariant data(const QModelIndex &index, int role) const override { Q_UNUSED(index); Q_UNUSED(role); return QVariant(); }
|
||||
|
||||
Q_INVOKABLE StateEvaluatorTemplate* get(int index) const {
|
||||
if (index < 0 || index >= m_list.count()) {
|
||||
return nullptr;
|
||||
}
|
||||
return m_list.at(index);
|
||||
}
|
||||
|
||||
void addStateEvaluatorTemplate(StateEvaluatorTemplate *stateEvaluatorTemplate) {
|
||||
stateEvaluatorTemplate->setParent(this);
|
||||
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||
m_list.append(stateEvaluatorTemplate);
|
||||
endInsertRows();
|
||||
}
|
||||
private:
|
||||
QList<StateEvaluatorTemplate*> m_list;
|
||||
};
|
||||
|
||||
#endif // STATEEVALUATORTEMPLATE_H
|
||||
@ -111,7 +111,6 @@ void TagsManager::handleTagsNotification(const QVariantMap ¶ms)
|
||||
|
||||
void TagsManager::getTagsReply(const QVariantMap ¶ms)
|
||||
{
|
||||
qDebug() << "Have tags" << params;
|
||||
foreach (const QVariant &tagVariant, params.value("params").toMap().value("tags").toList()) {
|
||||
addTagInternal(tagVariant.toMap());
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ EventDescriptor *EventDescriptors::get(int index) const
|
||||
|
||||
EventDescriptor *EventDescriptors::createNewEventDescriptor()
|
||||
{
|
||||
return new EventDescriptor();
|
||||
return new EventDescriptor(this);
|
||||
}
|
||||
|
||||
void EventDescriptors::addEventDescriptor(EventDescriptor *eventDescriptor)
|
||||
|
||||
@ -103,7 +103,6 @@ StateType *StateTypes::findByName(const QString &name) const
|
||||
void StateTypes::clearModel()
|
||||
{
|
||||
beginResetModel();
|
||||
qDebug() << "StateTypes: delete all stateTypes";
|
||||
qDeleteAll(m_stateTypes);
|
||||
m_stateTypes.clear();
|
||||
endResetModel();
|
||||
|
||||
@ -90,3 +90,6 @@ BR=$$BRANDING
|
||||
|
||||
target.path = /usr/bin
|
||||
INSTALLS += target
|
||||
|
||||
DISTFILES += \
|
||||
ui/magic/NewThingMagicPage.qml
|
||||
|
||||
@ -226,5 +226,6 @@
|
||||
<file>ui/images/awning/awning-070.svg</file>
|
||||
<file>ui/images/awning/awning-080.svg</file>
|
||||
<file>ui/images/awning/awning-090.svg</file>
|
||||
<file>ui/magic/NewThingMagicPage.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -109,6 +109,9 @@ ApplicationWindow {
|
||||
objectName: "pageStack"
|
||||
anchors.fill: parent
|
||||
initialItem: Page {}
|
||||
onDepthChanged: {
|
||||
print("stackview depth changed", pageStack.depth)
|
||||
}
|
||||
}
|
||||
|
||||
onClosing: {
|
||||
@ -244,6 +247,17 @@ ApplicationWindow {
|
||||
return "grey";
|
||||
}
|
||||
|
||||
function interfaceToDisplayName(name) {
|
||||
switch (name) {
|
||||
case "light":
|
||||
return qsTr("light")
|
||||
case "button":
|
||||
return "button";
|
||||
case "sensor":
|
||||
return qsTr("sensor")
|
||||
}
|
||||
}
|
||||
|
||||
function interfaceListToDevicePage(interfaceList) {
|
||||
var page;
|
||||
if (interfaceList.indexOf("media") >= 0) {
|
||||
|
||||
@ -9,6 +9,9 @@ Page {
|
||||
|
||||
property var device: null
|
||||
|
||||
Component.onCompleted: print("+++ created devicerulespage")
|
||||
Component.onDestruction: print("--- destroying devicerulespage")
|
||||
|
||||
header: GuhHeader {
|
||||
text: qsTr("Magic involving %1").arg(root.device.name)
|
||||
onBackPressed: pageStack.pop()
|
||||
@ -24,7 +27,14 @@ Page {
|
||||
// This Page will take ownership of the rule and delete it eventually.
|
||||
function addRule(rule) {
|
||||
if (rule === null || rule === undefined) {
|
||||
rule = Engine.ruleManager.createNewRule();
|
||||
d.editRulePage = pageStack.push(Qt.resolvedUrl("NewThingMagicPage.qml"), {device: root.device});
|
||||
d.editRulePage.manualCreation.connect(function() {
|
||||
pageStack.pop();
|
||||
rule = Engine.ruleManager.createNewRule();
|
||||
addRule(rule)
|
||||
})
|
||||
d.editRulePage.done.connect(function() {pageStack.pop(root);});
|
||||
return;
|
||||
}
|
||||
d.editRulePage = pageStack.push(Qt.resolvedUrl("EditRulePage.qml"), {rule: rule});
|
||||
d.editRulePage.StackView.onRemoved.connect(function() {
|
||||
@ -95,8 +105,11 @@ Page {
|
||||
|
||||
onDeleteClicked: Engine.ruleManager.removeRule(model.id)
|
||||
onClicked: {
|
||||
print("clicked")
|
||||
var newRule = rulesFilterModel.get(index).clone();
|
||||
print("rule cloned")
|
||||
d.editRulePage = pageStack.push(Qt.resolvedUrl("EditRulePage.qml"), {rule: newRule })
|
||||
print("page pushed")
|
||||
d.editRulePage.StackView.onRemoved.connect(function() {
|
||||
newRule.destroy();
|
||||
})
|
||||
|
||||
@ -13,7 +13,7 @@ Page {
|
||||
readonly property bool isEventBased: rule.eventDescriptors.count > 0 || rule.timeDescriptor.timeEventItems.count > 0
|
||||
readonly property bool isStateBased: (rule.stateEvaluator !== null || rule.timeDescriptor.calendarItems.count > 0) && !isEventBased
|
||||
readonly property bool actionsVisible: true
|
||||
readonly property bool exitActionsVisible: actionsVisible && isStateBased
|
||||
readonly property bool exitActionsVisible: (Engine.jsonRpcClient.ensureServerVersion(1.7) && !isEmpty) || isStateBased
|
||||
readonly property bool hasActions: rule.actions.count > 0
|
||||
readonly property bool hasExitActions: rule.exitActions.count > 0
|
||||
readonly property bool isEmpty: !isEventBased && !isStateBased && !hasActions
|
||||
@ -24,6 +24,9 @@ Page {
|
||||
signal accept();
|
||||
signal cancel();
|
||||
|
||||
Component.onCompleted: print("+++ created editrulepage")
|
||||
Component.onDestruction: print("--- destroying editrulepage")
|
||||
|
||||
function addEventDescriptor(interfaceMode) {
|
||||
if (interfaceMode === undefined) {
|
||||
interfaceMode = false;
|
||||
@ -396,9 +399,10 @@ Page {
|
||||
|
||||
Repeater {
|
||||
id: eventsRepeater
|
||||
model: root.hasExitActions ? null : root.rule.eventDescriptors
|
||||
model: root.rule.eventDescriptors
|
||||
delegate: EventDescriptorDelegate {
|
||||
Layout.fillWidth: true
|
||||
implicitWidth: parent.width
|
||||
eventDescriptor: root.rule.eventDescriptors.get(index)
|
||||
onRemoveEventDescriptor: root.rule.eventDescriptors.removeEventDescriptor(index)
|
||||
}
|
||||
@ -552,6 +556,7 @@ Page {
|
||||
model: root.actionsVisible ? root.rule.actions : null
|
||||
delegate: RuleActionDelegate {
|
||||
Layout.fillWidth: true
|
||||
implicitWidth: parent.width
|
||||
ruleAction: root.rule.actions.get(index)
|
||||
onRemoveRuleAction: root.rule.actions.removeRuleAction(index)
|
||||
}
|
||||
@ -574,7 +579,8 @@ Page {
|
||||
ThinDivider { visible: root.exitActionsVisible }
|
||||
|
||||
Label {
|
||||
text: qsTr("...isn't met any more, execute those actions:")
|
||||
text: root.isStateBased ? qsTr("...isn't met any more, execute those actions:") :
|
||||
qsTr("If the condition isn't met, execute those actions instead:")
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: app.margins
|
||||
wrapMode: Text.WordWrap
|
||||
@ -589,6 +595,7 @@ Page {
|
||||
model: root.exitActionsVisible ? root.rule.exitActions : null
|
||||
delegate: RuleActionDelegate {
|
||||
Layout.fillWidth: true
|
||||
implicitWidth: parent.width
|
||||
ruleAction: root.rule.exitActions.get(index)
|
||||
onClicked: root.rule.exitActions.removeRuleAction(index)
|
||||
}
|
||||
|
||||
297
nymea-app/ui/magic/NewThingMagicPage.qml
Normal file
297
nymea-app/ui/magic/NewThingMagicPage.qml
Normal file
@ -0,0 +1,297 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
import Nymea 1.0
|
||||
import "../components"
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
property var device: null
|
||||
readonly property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
||||
property bool busy: false
|
||||
|
||||
signal done();
|
||||
signal manualCreation();
|
||||
|
||||
function fillRuleFromTemplate(rule, ruleTemplate, selectedThings) {
|
||||
if (selectedThings === undefined) {
|
||||
selectedThings = [];
|
||||
}
|
||||
|
||||
// Fill in all EventDescriptors
|
||||
for (var i = rule.eventDescriptors.count; i < ruleTemplate.eventDescriptorTemplates.count; i++) {
|
||||
var eventDescriptorTemplate = ruleTemplate.eventDescriptorTemplates.get(i);
|
||||
// If we already have a thing selected for this selectionIndex, use that
|
||||
if (selectedThings.length > eventDescriptorTemplate.selectionId) {
|
||||
var device = Engine.deviceManager.devices.getDevice(selectedThings[eventDescriptorTemplate.selectionId]);
|
||||
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||
var eventDescriptor = rule.eventDescriptors.createNewEventDescriptor();
|
||||
eventDescriptor.deviceId = device.id
|
||||
eventDescriptor.eventTypeId = deviceClass.eventTypes.findByName(eventDescriptorTemplate.interfaceEvent).id
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return;
|
||||
}
|
||||
// Ok, we didn't pick a thing for this selectionId before. Did we already use the one we opened this page from?
|
||||
if (selectedThings.indexOf(root.device.id) === -1 && root.deviceClass.interfaces.indexOf(eventDescriptorTemplate.interfaceName) >= 0) {
|
||||
var eventDescriptor = rule.eventDescriptors.createNewEventDescriptor();
|
||||
eventDescriptor.deviceId = root.device.id;
|
||||
eventDescriptor.eventTypeId = root.deviceClass.eventTypes.findByName(eventDescriptorTemplate.interfaceEvent).id
|
||||
rule.eventDescriptors.addEventDescriptor(eventDescriptor);
|
||||
selectedThings.push(root.device.id);
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to pick a thing
|
||||
var page = pageStack.push(Qt.resolvedUrl("SelectThingPage.qml"), {shownInterfaces: [eventDescriptorTemplate.interfaceName]});
|
||||
page.thingSelected.connect(function(device) {
|
||||
var eventDescriptor = rule.eventDescriptors.createNewEventDescriptor();
|
||||
eventDescriptor.deviceId = device.id;
|
||||
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||
eventDescriptor.eventTypeId = deviceClass.eventTypes.findByName(eventDescriptorTemplate.interfaceEvent).id;
|
||||
rule.eventDescriptors.addEventDescriptor(eventDescriptor);
|
||||
selectedThings.push(device.id);
|
||||
fullRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return;
|
||||
})
|
||||
page.backPressed.connect(function() {rule.destroy(); root.done();})
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill in StateEvaluator
|
||||
if (ruleTemplate.stateEvaluatorTemplate !== null) {
|
||||
if (rule.stateEvaluator === null) {
|
||||
var stateEvaluator = rule.createStateEvaluator();
|
||||
rule.setStateEvaluator(stateEvaluator);
|
||||
fillStateEvaluatorFromTemplate(rule, ruleTemplate, stateEvaluator, ruleTemplate.stateEvaluatorTemplate, selectedThings);
|
||||
return;
|
||||
}
|
||||
var more = fillStateEvaluatorFromTemplate(rule, ruleTemplate, rule.stateEvaluator, ruleTemplate.stateEvaluatorTemplate, selectedThings);
|
||||
if (more) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = rule.actions.count; i < ruleTemplate.ruleActionTemplates.count; i++) {
|
||||
var ruleActionTemplate = ruleTemplate.ruleActionTemplates.get(i);
|
||||
|
||||
// Did we pick a thing for this index before?
|
||||
if (selectedThings.length > ruleActionTemplate.selectionId) {
|
||||
var ruleAction = rule.actions.createNewRuleAction();
|
||||
var deviceId = selectedThings[ruleActionTemplate.selectionId];
|
||||
var device = Engine.deviceManager.devices.getDevice(deviceId);
|
||||
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||
ruleAction.deviceId = deviceId;
|
||||
ruleAction.actionTypeId = deviceClass.actionTypes.findByName(ruleActionTemplate.interfaceAction).id
|
||||
for (var j = 0; j < ruleActionTemplate.ruleActionParams.count; j++) {
|
||||
var ruleActionParam = ruleActionTemplate.ruleActionParams.get(j)
|
||||
var actionType = deviceClass.actionTypes.getActionType(ruleAction.actionTypeId);
|
||||
var paramType = actionType.paramTypes.findByName(ruleActionParam.paramName);
|
||||
ruleAction.ruleActionParams.setRuleActionParam(paramType.id, ruleActionParam.value)
|
||||
}
|
||||
rule.actions.addRuleAction(ruleAction);
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return;
|
||||
}
|
||||
|
||||
// Did we already use the thing we opened this page from?
|
||||
if (selectedThings.indexOf(root.device.id) === -1 && root.deviceClass.interfaces.indexOf(ruleActionTemplate.interfaceName) >= 0) {
|
||||
var ruleAction = rule.actions.createNewRuleAction();
|
||||
ruleAction.deviceId = root.device.id;
|
||||
ruleAction.actionTypeId = root.deviceClass.actionTypes.findByName(ruleActionTemplate.interfaceAction).id
|
||||
for (var j = 0; j < ruleActionTemplate.ruleActionParams.count; j++) {
|
||||
var ruleActionParam = ruleActionTemplate.ruleActionParams.get(j)
|
||||
var actionType = deviceClass.actionTypes.getActionType(ruleAction.actionTypeId);
|
||||
var paramType = actionType.paramTypes.findByName(ruleActionParam.paramName);
|
||||
ruleAction.ruleActionParams.setRuleActionParam(paramType.id, ruleActionParam.value)
|
||||
}
|
||||
rule.actions.addRuleAction(ruleAction);
|
||||
selectedThings.push(root.device.id);
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ok, we need to pick a thing
|
||||
var page = pageStack.push(Qt.resolvedUrl("SelectThingPage.qml"), {shownInterfaces: [ruleActionTemplate.interfaceName]});
|
||||
page.thingSelected.connect(function(device) {
|
||||
var ruleAction = rule.actions.createNewRuleAction();
|
||||
ruleAction.deviceId = device.id;
|
||||
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||
ruleAction.actionTypeId = deviceClass.actionTypes.findByName(ruleActionTemplate.interfaceAction).id;
|
||||
for (var j = 0; j < ruleActionTemplate.ruleActionParams.count; j++) {
|
||||
var ruleActionParam = ruleActionTemplate.ruleActionParams.get(j)
|
||||
var actionType = deviceClass.actionTypes.getActionType(ruleAction.actionTypeId);
|
||||
var paramType = actionType.paramTypes.findByName(ruleActionParam.paramName);
|
||||
ruleAction.ruleActionParams.setRuleActionParam(paramType.id, ruleActionParam.value)
|
||||
}
|
||||
rule.actions.addRuleAction(ruleAction);
|
||||
selectedThings.push(device.id);
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return;
|
||||
})
|
||||
page.backPressed.connect(function() {rule.destroy(); root.done();})
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (var i = rule.exitActions.count; i < ruleTemplate.ruleExitActionTemplates.count; i++) {
|
||||
var ruleExitActionTemplate = ruleTemplate.ruleExitActionTemplates.get(i);
|
||||
|
||||
// Did we pick a thing for this index before?
|
||||
if (selectedThings.length > ruleExitActionTemplate.selectionId) {
|
||||
var ruleAction = rule.exitActions.createNewRuleAction();
|
||||
var deviceId = selectedThings[ruleExitActionTemplate.selectionId];
|
||||
var device = Engine.deviceManager.devices.getDevice(deviceId);
|
||||
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||
ruleAction.deviceId = deviceId;
|
||||
ruleAction.actionTypeId = deviceClass.actionTypes.findByName(ruleExitActionTemplate.interfaceAction).id
|
||||
for (var j = 0; j < ruleExitActionTemplate.ruleActionParams.count; j++) {
|
||||
var ruleActionParam = ruleExitActionTemplate.ruleActionParams.get(j)
|
||||
var actionType = deviceClass.actionTypes.getActionType(ruleAction.actionTypeId);
|
||||
var paramType = actionType.paramTypes.findByName(ruleActionParam.paramName);
|
||||
ruleAction.ruleActionParams.setRuleActionParam(paramType.id, ruleActionParam.value)
|
||||
}
|
||||
rule.exitActions.addRuleAction(ruleAction);
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return;
|
||||
}
|
||||
|
||||
// Did we already use the thing we opened this page from?
|
||||
if (selectedThings.indexOf(root.device.id) === -1 && root.deviceClass.interfaces.indexOf(ruleExitActionTemplate.interfaceName) >= 0) {
|
||||
var ruleAction = rule.exitActions.createNewRuleAction();
|
||||
ruleAction.deviceId = root.device.id;
|
||||
ruleAction.actionTypeId = root.deviceClass.actionTypes.findByName(ruleExitActionTemplate.interfaceAction).id
|
||||
for (var j = 0; j < ruleExitActionTemplate.ruleActionParams.count; j++) {
|
||||
var ruleActionParam = ruleExitActionTemplate.ruleActionParams.get(j)
|
||||
var actionType = deviceClass.actionTypes.getActionType(ruleAction.actionTypeId);
|
||||
var paramType = actionType.paramTypes.findByName(ruleActionParam.paramName);
|
||||
ruleAction.ruleActionParams.setRuleActionParam(paramType.id, ruleActionParam.value)
|
||||
}
|
||||
rule.exitActions.addRuleAction(ruleAction);
|
||||
selectedThings.push(root.device.id);
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ok, we need to pick a thing
|
||||
var page = pageStack.push(Qt.resolvedUrl("SelectThingPage.qml"), {shownInterfaces: [ruleExitActionTemplate.interfaceName]});
|
||||
page.thingSelected.connect(function(device) {
|
||||
var ruleAction = rule.exitActions.createNewRuleAction();
|
||||
ruleAction.deviceId = device.id;
|
||||
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||
ruleAction.actionTypeId = deviceClass.actionTypes.findByName(ruleExitActionTemplate.interfaceAction).id;
|
||||
for (var j = 0; j < ruleExitActionTemplate.ruleActionParams.count; j++) {
|
||||
var ruleActionParam = ruleExitActionTemplate.ruleActionParams.get(j)
|
||||
var actionType = deviceClass.actionTypes.getActionType(ruleAction.actionTypeId);
|
||||
var paramType = actionType.paramTypes.findByName(ruleActionParam.paramName);
|
||||
ruleAction.ruleActionParams.setRuleActionParam(paramType.id, ruleActionParam.value)
|
||||
}
|
||||
rule.exitActions.addRuleAction(ruleAction);
|
||||
selectedThings.push(device.id);
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return;
|
||||
})
|
||||
page.backPressed.connect(function() {rule.destroy(); root.done();})
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
rule.name = ruleTemplate.ruleNameTemplate;
|
||||
for (var i = 0; i < selectedThings.length; i++) {
|
||||
var device = Engine.deviceManager.devices.getDevice(selectedThings[i]);
|
||||
rule.name = rule.name.arg(device.name)
|
||||
}
|
||||
|
||||
print("Rule complete!")
|
||||
Engine.ruleManager.addRule(rule);
|
||||
rule.destroy();
|
||||
root.done();
|
||||
}
|
||||
|
||||
function fillStateEvaluatorFromTemplate(rule, ruleTemplate, stateEvaluator, stateEvaluatorTemplate, selectedThings) {
|
||||
if (stateEvaluatorTemplate.stateDescriptorTemplate !== null && selectedThings.indexOf(stateEvaluator.stateDescriptor.deviceId) === -1) {
|
||||
// need to fill stateDescriptor
|
||||
// did we pick a thing for this index before?
|
||||
if (selectedThings.length > stateEvaluatorTemplate.stateDescriptorTemplate.selectionId) {
|
||||
var deviceId = selectedThings[stateEvaluatorTemplate.stateDescriptorTemplate.selectionId]
|
||||
var device = Engine.deviceManager.devices.getDevice(deviceId)
|
||||
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||
stateEvaluator.stateDescriptor.deviceId = deviceId;
|
||||
stateEvaluator.stateDescriptor.stateTypeId = deviceClass.stateTypes.findByName(stateEvaluatorTemplate.stateDescriptorTemplate.interfaceState).id
|
||||
stateEvaluator.stateDescriptor.valueOperator = stateEvaluatorTemplate.stateDescriptorTemplate.valueOperator;
|
||||
stateEvaluator.stateDescriptor.value = stateEvaluatorTemplate.stateDescriptorTemplate.value;
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return true;
|
||||
}
|
||||
if (selectedThings.indexOf(root.device.id) === -1 && root.deviceClass.interfaces.indexOf(stateEvaluatorTemplate.stateDescriptorTemplate.interfaceName) >= 0) {
|
||||
stateEvaluator.stateDescriptor.deviceId = root.device.id;
|
||||
stateEvaluator.stateDescriptor.stateTypeId = root.deviceClass.stateTypes.findByName(stateEvaluatorTemplate.stateDescriptorTemplate.interfaceState).id
|
||||
stateEvaluator.stateDescriptor.valueOperator = stateEvaluatorTemplate.stateDescriptorTemplate.valueOperator;
|
||||
stateEvaluator.stateDescriptor.value = stateEvaluatorTemplate.stateDescriptorTemplate.value;
|
||||
selectedThings.push(root.device.id);
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings);
|
||||
return true;
|
||||
}
|
||||
var page = pageStack.push(Qt.resolvedUrl("SelectThingPage.qml"), {shownInterfaces: [stateEvaluatorTemplate.stateDescriptorTemplate.interfaceName]});
|
||||
page.thingSelected.connect(function(device) {
|
||||
var deviceClass = Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||
stateEvaluator.stateDescriptor.deviceId = device.id;
|
||||
stateEvaluator.stateDescriptor.stateTypeId = deviceClass.stateTypes.findByName(stateEvaluatorTemplate.stateDescriptorTemplate.interfaceState).id;
|
||||
stateEvaluator.stateDescriptor.valueOperator = stateEvaluatorTemplate.stateDescriptorTemplate.valueOperator;
|
||||
stateEvaluator.stateDescriptor.value = stateEvaluatorTemplate.stateDescriptorTemplate.value;
|
||||
selectedThings.push(device.id);
|
||||
fillRuleFromTemplate(rule, ruleTemplate, selectedThings)
|
||||
})
|
||||
page.backPressed.connect(function() {rule.destroy(); root.done();})
|
||||
return true;
|
||||
}
|
||||
stateEvaluator.stateOperator = stateEvaluatorTemplate.stateOperator;
|
||||
if (stateEvaluatorTemplate.childEvaluatorTemplates.count > stateEvaluator.childEvaluators.count) {
|
||||
var childEvaluator = rule.createStateEvaluator();
|
||||
var more = fillStateEvaluatorFromTemplate(rule, ruleTemplate, childEvaluator, stateEvaluatorTemplate.childEvaluatorTemplates.get(stateEvaluator.childEvaluators.count))
|
||||
stateEvaluator.childEvaluators.addStateEvaluator(childEvaluator);
|
||||
return more;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
header: GuhHeader {
|
||||
text: qsTr("New magic")
|
||||
onBackPressed: root.done()
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
ListView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: RuleTemplatesFilterModel {
|
||||
id: ruleTemplatesModel
|
||||
ruleTemplates: RuleTemplates {}
|
||||
filterInterfaceNames: root.deviceClass ? root.deviceClass.interfaces : []
|
||||
}
|
||||
delegate: MeaListItemDelegate {
|
||||
width: parent.width
|
||||
text: model.description
|
||||
|
||||
onClicked: {
|
||||
var ruleTemplate = ruleTemplatesModel.get(index);
|
||||
var rule = Engine.ruleManager.createNewRule();
|
||||
root.fillRuleFromTemplate(rule, ruleTemplate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThinDivider {}
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: app.margins
|
||||
text: qsTr("Create some magic manually")
|
||||
onClicked: {
|
||||
root.manualCreation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,9 +15,12 @@ Page {
|
||||
property alias showEvents: interfacesProxy.showEvents
|
||||
property alias showActions: interfacesProxy.showActions
|
||||
property alias showStates: interfacesProxy.showStates
|
||||
property alias shownInterfaces: devicesProxy.shownInterfaces
|
||||
|
||||
header: GuhHeader {
|
||||
text: root.selectInterface ? qsTr("Select a kind of things") : qsTr("Select a thing")
|
||||
text: root.selectInterface ?
|
||||
qsTr("Select a kind of things") :
|
||||
root.shownInterfaces.length > 0 ? qsTr("Select a %1").arg(app.interfaceToDisplayName(root.shownInterfaces[0])) : qsTr("Select a thing")
|
||||
onBackPressed: root.backPressed()
|
||||
}
|
||||
|
||||
@ -26,13 +29,18 @@ Page {
|
||||
devicesFilter: Engine.deviceManager.devices
|
||||
}
|
||||
|
||||
DevicesProxy {
|
||||
id: devicesProxy
|
||||
devices: Engine.deviceManager.devices
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
ListView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: root.selectInterface ? interfacesProxy : Engine.deviceManager.devices
|
||||
model: root.selectInterface ? interfacesProxy : devicesProxy
|
||||
clip: true
|
||||
delegate: MeaListItemDelegate {
|
||||
width: parent.width
|
||||
@ -42,7 +50,7 @@ Page {
|
||||
if (root.selectInterface) {
|
||||
root.interfaceSelected(interfacesProxy.get(index).name)
|
||||
} else {
|
||||
root.thingSelected(Engine.deviceManager.devices.get(index))
|
||||
root.thingSelected(devicesProxy.get(index))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user