add support for time based rules and rework rule dialog
This commit is contained in:
parent
3566977f18
commit
6fa3604f52
@ -34,6 +34,12 @@
|
|||||||
#include "types/stateevaluator.h"
|
#include "types/stateevaluator.h"
|
||||||
#include "types/stateevaluators.h"
|
#include "types/stateevaluators.h"
|
||||||
#include "types/statedescriptor.h"
|
#include "types/statedescriptor.h"
|
||||||
|
#include "types/timeeventitem.h"
|
||||||
|
#include "types/timeeventitems.h"
|
||||||
|
#include "types/timedescriptor.h"
|
||||||
|
#include "types/repeatingoption.h"
|
||||||
|
#include "types/calendaritems.h"
|
||||||
|
#include "types/calendaritem.h"
|
||||||
|
|
||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
|
|
||||||
@ -245,6 +251,10 @@ QVariantMap JsonTypes::packRule(Rule *rule)
|
|||||||
ret.insert("eventDescriptors", packEventDescriptors(rule->eventDescriptors()));
|
ret.insert("eventDescriptors", packEventDescriptors(rule->eventDescriptors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rule->timeDescriptor()->timeEventItems()->rowCount() > 0 || rule->timeDescriptor()->calendarItems()->rowCount() > 0) {
|
||||||
|
ret.insert("timeDescriptor", packTimeDescriptor(rule->timeDescriptor()));
|
||||||
|
}
|
||||||
|
|
||||||
if (rule->stateEvaluator()) {
|
if (rule->stateEvaluator()) {
|
||||||
ret.insert("stateEvaluator", packStateEvaluator(rule->stateEvaluator()));
|
ret.insert("stateEvaluator", packStateEvaluator(rule->stateEvaluator()));
|
||||||
}
|
}
|
||||||
@ -338,6 +348,67 @@ QVariantMap JsonTypes::packStateEvaluator(StateEvaluator *stateEvaluator)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantMap JsonTypes::packTimeDescriptor(TimeDescriptor *timeDescriptor)
|
||||||
|
{
|
||||||
|
QVariantMap ret;
|
||||||
|
QVariantList timeEventItems;
|
||||||
|
for (int i = 0; i < timeDescriptor->timeEventItems()->rowCount(); i++) {
|
||||||
|
timeEventItems.append(packTimeEventItem(timeDescriptor->timeEventItems()->get(i)));
|
||||||
|
}
|
||||||
|
if (!timeEventItems.isEmpty()) {
|
||||||
|
ret.insert("timeEventItems", timeEventItems);
|
||||||
|
}
|
||||||
|
QVariantList calendarItems;
|
||||||
|
for (int i = 0; i < timeDescriptor->calendarItems()->rowCount(); i++) {
|
||||||
|
calendarItems.append(packCalendarItem(timeDescriptor->calendarItems()->get(i)));
|
||||||
|
}
|
||||||
|
if (!calendarItems.isEmpty()) {
|
||||||
|
ret.insert("calendarItems", calendarItems);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap JsonTypes::packTimeEventItem(TimeEventItem *timeEventItem)
|
||||||
|
{
|
||||||
|
QVariantMap ret;
|
||||||
|
if (!timeEventItem->time().isNull()) {
|
||||||
|
ret.insert("time", timeEventItem->time().toString("hh:mm"));
|
||||||
|
}
|
||||||
|
if (!timeEventItem->dateTime().isNull()) {
|
||||||
|
ret.insert("dateTime", timeEventItem->dateTime().toSecsSinceEpoch());
|
||||||
|
}
|
||||||
|
ret.insert("repeating", packRepeatingOption(timeEventItem->repeatingOption()));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap JsonTypes::packCalendarItem(CalendarItem *calendarItem)
|
||||||
|
{
|
||||||
|
QVariantMap ret;
|
||||||
|
ret.insert("duration", calendarItem->duration());
|
||||||
|
if (!calendarItem->dateTime().isNull()) {
|
||||||
|
ret.insert("datetime", calendarItem->dateTime().toSecsSinceEpoch());
|
||||||
|
}
|
||||||
|
if (!calendarItem->startTime().isNull()) {
|
||||||
|
ret.insert("startTime", calendarItem->startTime().toString("hh:mm"));
|
||||||
|
}
|
||||||
|
ret.insert("repeating", packRepeatingOption(calendarItem->repeatingOption()));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap JsonTypes::packRepeatingOption(RepeatingOption *repeatingOption)
|
||||||
|
{
|
||||||
|
QVariantMap ret;
|
||||||
|
QMetaEnum repeatingModeEnum = QMetaEnum::fromType<RepeatingOption::RepeatingMode>();
|
||||||
|
ret.insert("mode", repeatingModeEnum.valueToKey(repeatingOption->repeatingMode()));
|
||||||
|
if (!repeatingOption->weekDays().isEmpty()) {
|
||||||
|
ret.insert("weekDays", repeatingOption->weekDays());
|
||||||
|
}
|
||||||
|
if (!repeatingOption->monthDays().isEmpty()) {
|
||||||
|
ret.insert("monthDays", repeatingOption->monthDays());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
DeviceClass::SetupMethod JsonTypes::stringToSetupMethod(const QString &setupMethodString)
|
DeviceClass::SetupMethod JsonTypes::stringToSetupMethod(const QString &setupMethodString)
|
||||||
{
|
{
|
||||||
if (setupMethodString == "SetupMethodJustAdd") {
|
if (setupMethodString == "SetupMethodJustAdd") {
|
||||||
|
|||||||
@ -43,6 +43,10 @@ class Rule;
|
|||||||
class StateEvaluator;
|
class StateEvaluator;
|
||||||
class RuleActions;
|
class RuleActions;
|
||||||
class EventDescriptors;
|
class EventDescriptors;
|
||||||
|
class TimeDescriptor;
|
||||||
|
class TimeEventItem;
|
||||||
|
class CalendarItem;
|
||||||
|
class RepeatingOption;
|
||||||
|
|
||||||
class JsonTypes : public QObject
|
class JsonTypes : public QObject
|
||||||
{
|
{
|
||||||
@ -65,6 +69,11 @@ public:
|
|||||||
static QVariantList packEventDescriptors(EventDescriptors* eventDescriptors);
|
static QVariantList packEventDescriptors(EventDescriptors* eventDescriptors);
|
||||||
static QVariantMap packParam(Param *param);
|
static QVariantMap packParam(Param *param);
|
||||||
static QVariantMap packStateEvaluator(StateEvaluator* stateEvaluator);
|
static QVariantMap packStateEvaluator(StateEvaluator* stateEvaluator);
|
||||||
|
static QVariantMap packTimeDescriptor(TimeDescriptor* timeDescriptor);
|
||||||
|
static QVariantMap packTimeEventItem(TimeEventItem* timeEventItem);
|
||||||
|
static QVariantMap packCalendarItem(CalendarItem* calendarItem);
|
||||||
|
static QVariantMap packRepeatingOption(RepeatingOption* repeatingOption);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static DeviceClass::SetupMethod stringToSetupMethod(const QString &setupMethodString);
|
static DeviceClass::SetupMethod stringToSetupMethod(const QString &setupMethodString);
|
||||||
static QList<DeviceClass::BasicTag> stringListToBasicTags(const QStringList &basicTagsStringList);
|
static QList<DeviceClass::BasicTag> stringListToBasicTags(const QStringList &basicTagsStringList);
|
||||||
|
|||||||
@ -18,6 +18,12 @@
|
|||||||
#include "types/ruleactionparam.h"
|
#include "types/ruleactionparam.h"
|
||||||
#include "types/eventdescriptors.h"
|
#include "types/eventdescriptors.h"
|
||||||
#include "types/eventdescriptor.h"
|
#include "types/eventdescriptor.h"
|
||||||
|
#include "types/timedescriptor.h"
|
||||||
|
#include "types/timeeventitems.h"
|
||||||
|
#include "types/timeeventitem.h"
|
||||||
|
#include "types/repeatingoption.h"
|
||||||
|
#include "types/calendaritems.h"
|
||||||
|
#include "types/calendaritem.h"
|
||||||
#include "types/rule.h"
|
#include "types/rule.h"
|
||||||
#include "types/interfaces.h"
|
#include "types/interfaces.h"
|
||||||
#include "types/interface.h"
|
#include "types/interface.h"
|
||||||
@ -104,6 +110,12 @@ void registerQmlTypes() {
|
|||||||
qmlRegisterUncreatableType<StateDescriptor>(uri, 1, 0, "StateDescriptor", "Uncreatable");
|
qmlRegisterUncreatableType<StateDescriptor>(uri, 1, 0, "StateDescriptor", "Uncreatable");
|
||||||
qmlRegisterUncreatableType<StateEvaluator>(uri, 1, 0, "StateEvaluator", "Uncreatable");
|
qmlRegisterUncreatableType<StateEvaluator>(uri, 1, 0, "StateEvaluator", "Uncreatable");
|
||||||
qmlRegisterUncreatableType<StateEvaluators>(uri, 1, 0, "StateEvaluators", "Uncreatable");
|
qmlRegisterUncreatableType<StateEvaluators>(uri, 1, 0, "StateEvaluators", "Uncreatable");
|
||||||
|
qmlRegisterUncreatableType<TimeDescriptor>(uri, 1, 0, "TimeDescriptor", "Uncreatable");
|
||||||
|
qmlRegisterUncreatableType<TimeEventItems>(uri, 1, 0, "TimeEventItems", "Uncreatable");
|
||||||
|
qmlRegisterUncreatableType<TimeEventItem>(uri, 1, 0, "TimeEventItem", "Uncreatable");
|
||||||
|
qmlRegisterUncreatableType<RepeatingOption>(uri, 1, 0, "RepeatingOption", "Uncreatable");
|
||||||
|
qmlRegisterUncreatableType<CalendarItems>(uri, 1, 0, "CalendarItems", "Uncreatable");
|
||||||
|
qmlRegisterUncreatableType<CalendarItem>(uri, 1, 0, "CalendarItem", "Uncreatable");
|
||||||
|
|
||||||
qmlRegisterUncreatableType<Interface>(uri, 1, 0, "Interface", "Uncreatable");
|
qmlRegisterUncreatableType<Interface>(uri, 1, 0, "Interface", "Uncreatable");
|
||||||
qmlRegisterSingletonType<Interfaces>(uri, 1, 0, "Interfaces", interfacesModel_provider);
|
qmlRegisterSingletonType<Interfaces>(uri, 1, 0, "Interfaces", interfacesModel_provider);
|
||||||
|
|||||||
@ -12,7 +12,12 @@
|
|||||||
#include "types/stateevaluator.h"
|
#include "types/stateevaluator.h"
|
||||||
#include "types/stateevaluators.h"
|
#include "types/stateevaluators.h"
|
||||||
#include "types/statedescriptor.h"
|
#include "types/statedescriptor.h"
|
||||||
|
#include "types/timedescriptor.h"
|
||||||
|
#include "types/timeeventitems.h"
|
||||||
#include "types/timeeventitem.h"
|
#include "types/timeeventitem.h"
|
||||||
|
#include "types/repeatingoption.h"
|
||||||
|
#include "types/calendaritems.h"
|
||||||
|
#include "types/calendaritem.h"
|
||||||
|
|
||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
|
|
||||||
@ -179,6 +184,7 @@ Rule *RuleManager::parseRule(const QVariantMap &ruleMap)
|
|||||||
parseEventDescriptors(ruleMap.value("eventDescriptors").toList(), rule);
|
parseEventDescriptors(ruleMap.value("eventDescriptors").toList(), rule);
|
||||||
parseRuleActions(ruleMap.value("actions").toList(), rule);
|
parseRuleActions(ruleMap.value("actions").toList(), rule);
|
||||||
parseRuleExitActions(ruleMap.value("exitActions").toList(), rule);
|
parseRuleExitActions(ruleMap.value("exitActions").toList(), rule);
|
||||||
|
parseTimeDescriptor(ruleMap.value("timeDescriptor").toMap(), rule);
|
||||||
rule->setStateEvaluator(parseStateEvaluator(ruleMap.value("stateEvaluator").toMap()));
|
rule->setStateEvaluator(parseStateEvaluator(ruleMap.value("stateEvaluator").toMap()));
|
||||||
return rule;
|
return rule;
|
||||||
}
|
}
|
||||||
@ -259,12 +265,36 @@ void RuleManager::parseRuleExitActions(const QVariantList &ruleActions, Rule *ru
|
|||||||
|
|
||||||
void RuleManager::parseTimeDescriptor(const QVariantMap &timeDescriptor, Rule *rule)
|
void RuleManager::parseTimeDescriptor(const QVariantMap &timeDescriptor, Rule *rule)
|
||||||
{
|
{
|
||||||
Q_UNUSED(rule)
|
foreach (const QVariant &timeEventItemVariant, timeDescriptor.value("timeEventItems").toList()) {
|
||||||
Q_UNUSED(timeDescriptor)
|
TimeEventItem *timeEventItem = new TimeEventItem();
|
||||||
// foreach (const QVariant &timeEventItemVariant, timeDescriptor.value("timeEventItems").toList()) {
|
if (timeEventItemVariant.toMap().contains("datetime")) {
|
||||||
// TimeEventItem *timeEventItem = new TimeEventItem();
|
timeEventItem->setDateTime(QDateTime::fromSecsSinceEpoch(timeEventItemVariant.toMap().value("datetime").toULongLong()));
|
||||||
// timeEventItem->setDateTime(QDateTime::fromSecsSinceEpoch(timeEventItemVariant.toMap().value("datetime").toULongLong()));
|
}
|
||||||
// timeEventItem->setTime(QTime::fromString(timeEventItemVariant.toMap().value("time").toString()));
|
if (timeEventItemVariant.toMap().contains("time")){
|
||||||
// timeEventItem->setRepeatingOption();
|
timeEventItem->setTime(QTime::fromString(timeEventItemVariant.toMap().value("time").toString()));
|
||||||
// }
|
}
|
||||||
|
QVariantMap repeatingOptionMap = timeEventItemVariant.toMap().value("repeating").toMap();
|
||||||
|
QMetaEnum modeEnum = QMetaEnum::fromType<RepeatingOption::RepeatingMode>();
|
||||||
|
timeEventItem->repeatingOption()->setRepeatingMode((RepeatingOption::RepeatingMode)modeEnum.keyToValue(repeatingOptionMap.value("mode").toByteArray()));
|
||||||
|
timeEventItem->repeatingOption()->setWeekDays(repeatingOptionMap.value("weekDays").toList());
|
||||||
|
timeEventItem->repeatingOption()->setMonthDays(repeatingOptionMap.value("monthDays").toList());
|
||||||
|
rule->timeDescriptor()->timeEventItems()->addTimeEventItem(timeEventItem);
|
||||||
|
}
|
||||||
|
foreach (const QVariant &calendarItemVariant, timeDescriptor.value("calendarItems").toList()) {
|
||||||
|
CalendarItem *calendarItem = new CalendarItem();
|
||||||
|
if (calendarItemVariant.toMap().contains("datetime")) {
|
||||||
|
calendarItem->setDateTime(QDateTime::fromSecsSinceEpoch(calendarItemVariant.toMap().value("datetime").toULongLong()));
|
||||||
|
}
|
||||||
|
if (calendarItemVariant.toMap().contains("startTime")) {
|
||||||
|
calendarItem->setStartTime(QTime::fromString(calendarItemVariant.toMap().value("startTime").toString()));
|
||||||
|
}
|
||||||
|
calendarItem->setDuration(calendarItemVariant.toMap().value("duration").toInt());
|
||||||
|
QVariantMap repeatingOptionMap = calendarItemVariant.toMap().value("repeating").toMap();
|
||||||
|
QMetaEnum modeEnum = QMetaEnum::fromType<RepeatingOption::RepeatingMode>();
|
||||||
|
calendarItem->repeatingOption()->setRepeatingMode((RepeatingOption::RepeatingMode)modeEnum.keyToValue(repeatingOptionMap.value("mode").toByteArray()));
|
||||||
|
calendarItem->repeatingOption()->setWeekDays(repeatingOptionMap.value("weekDays").toList());
|
||||||
|
calendarItem->repeatingOption()->setMonthDays(repeatingOptionMap.value("monthDays").toList());
|
||||||
|
rule->timeDescriptor()->calendarItems()->addCalendarItem(calendarItem);
|
||||||
|
}
|
||||||
|
// rule->timeDescriptor()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,7 +51,8 @@ HEADERS += \
|
|||||||
types/timeeventitem.h \
|
types/timeeventitem.h \
|
||||||
types/calendaritem.h \
|
types/calendaritem.h \
|
||||||
types/timeeventitems.h \
|
types/timeeventitems.h \
|
||||||
types/calendaritems.h
|
types/calendaritems.h \
|
||||||
|
types/repeatingoption.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
types/vendor.cpp \
|
types/vendor.cpp \
|
||||||
@ -93,7 +94,8 @@ SOURCES += \
|
|||||||
types/timeeventitem.cpp \
|
types/timeeventitem.cpp \
|
||||||
types/calendaritem.cpp \
|
types/calendaritem.cpp \
|
||||||
types/timeeventitems.cpp \
|
types/timeeventitems.cpp \
|
||||||
types/calendaritems.cpp
|
types/calendaritems.cpp \
|
||||||
|
types/repeatingoption.cpp
|
||||||
|
|
||||||
# install header file with relative subdirectory
|
# install header file with relative subdirectory
|
||||||
for(header, HEADERS) {
|
for(header, HEADERS) {
|
||||||
|
|||||||
@ -1,6 +1,62 @@
|
|||||||
#include "calendaritem.h"
|
#include "calendaritem.h"
|
||||||
|
|
||||||
|
#include "repeatingoption.h"
|
||||||
|
|
||||||
CalendarItem::CalendarItem(QObject *parent) : QObject(parent)
|
CalendarItem::CalendarItem(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
|
m_repeatingOption = new RepeatingOption(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CalendarItem::duration() const
|
||||||
|
{
|
||||||
|
return m_duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalendarItem::setDuration(int duration)
|
||||||
|
{
|
||||||
|
if (m_duration != duration) {
|
||||||
|
m_duration = duration;
|
||||||
|
emit durationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime CalendarItem::dateTime() const
|
||||||
|
{
|
||||||
|
return m_dateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalendarItem::setDateTime(const QDateTime &dateTime)
|
||||||
|
{
|
||||||
|
if (m_dateTime != dateTime) {
|
||||||
|
m_dateTime = dateTime;
|
||||||
|
emit dateTimeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QTime CalendarItem::startTime() const
|
||||||
|
{
|
||||||
|
return m_startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalendarItem::setStartTime(const QTime &startTime)
|
||||||
|
{
|
||||||
|
if (m_startTime != startTime) {
|
||||||
|
m_startTime = startTime;
|
||||||
|
emit startTimeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RepeatingOption *CalendarItem::repeatingOption() const
|
||||||
|
{
|
||||||
|
return m_repeatingOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
CalendarItem *CalendarItem::clone() const
|
||||||
|
{
|
||||||
|
CalendarItem* ret = new CalendarItem();
|
||||||
|
ret->m_dateTime = this->m_dateTime;
|
||||||
|
ret->m_duration = this->m_duration;
|
||||||
|
ret->m_repeatingOption = this->m_repeatingOption;
|
||||||
|
ret->m_startTime = this->m_startTime;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,16 +2,44 @@
|
|||||||
#define CALENDARITEM_H
|
#define CALENDARITEM_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
class RepeatingOption;
|
||||||
|
|
||||||
class CalendarItem : public QObject
|
class CalendarItem : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
|
||||||
|
Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged)
|
||||||
|
Q_PROPERTY(QTime startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
|
||||||
|
Q_PROPERTY(RepeatingOption* repeatingOption READ repeatingOption CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CalendarItem(QObject *parent = nullptr);
|
explicit CalendarItem(QObject *parent = nullptr);
|
||||||
|
|
||||||
signals:
|
int duration() const;
|
||||||
|
void setDuration(int duration);
|
||||||
|
|
||||||
public slots:
|
QDateTime dateTime() const;
|
||||||
|
void setDateTime(const QDateTime &dateTime);
|
||||||
|
|
||||||
|
QTime startTime() const;
|
||||||
|
void setStartTime(const QTime &startTime);
|
||||||
|
|
||||||
|
RepeatingOption* repeatingOption() const;
|
||||||
|
|
||||||
|
CalendarItem* clone() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void durationChanged();
|
||||||
|
void dateTimeChanged();
|
||||||
|
void startTimeChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_duration = 0;
|
||||||
|
QDateTime m_dateTime;
|
||||||
|
QTime m_startTime;
|
||||||
|
RepeatingOption* m_repeatingOption = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CALENDARITEM_H
|
#endif // CALENDARITEM_H
|
||||||
@ -1,6 +1,50 @@
|
|||||||
#include "calendaritems.h"
|
#include "calendaritems.h"
|
||||||
|
#include "calendaritem.h"
|
||||||
|
|
||||||
CalendarItems::CalendarItems(QObject *parent) : QObject(parent)
|
CalendarItems::CalendarItems(QObject *parent) : QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CalendarItems::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return m_list.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CalendarItems::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalendarItems::addCalendarItem(CalendarItem *calendarItem)
|
||||||
|
{
|
||||||
|
calendarItem->setParent(this);
|
||||||
|
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||||
|
m_list.append(calendarItem);
|
||||||
|
endInsertRows();
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalendarItems::removeCalendarItem(int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index > m_list.count()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
beginRemoveRows(QModelIndex(), index, index);
|
||||||
|
m_list.takeAt(index)->deleteLater();
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
CalendarItem *CalendarItems::createNewCalendarItem() const
|
||||||
|
{
|
||||||
|
return new CalendarItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
CalendarItem *CalendarItems::get(int index) const
|
||||||
|
{
|
||||||
|
if (index < 0 || index > m_list.count()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return m_list.at(index);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,17 +1,31 @@
|
|||||||
#ifndef CALENDARITEMS_H
|
#ifndef CALENDARITEMS_H
|
||||||
#define CALENDARITEMS_H
|
#define CALENDARITEMS_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
class CalendarItems : public QObject
|
class CalendarItem;
|
||||||
|
|
||||||
|
class CalendarItems : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||||
public:
|
public:
|
||||||
explicit CalendarItems(QObject *parent = nullptr);
|
explicit CalendarItems(QObject *parent = nullptr);
|
||||||
|
|
||||||
signals:
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
|
||||||
public slots:
|
Q_INVOKABLE void addCalendarItem(CalendarItem* calendarItem);
|
||||||
|
Q_INVOKABLE void removeCalendarItem(int index);
|
||||||
|
|
||||||
|
Q_INVOKABLE CalendarItem* createNewCalendarItem() const;
|
||||||
|
Q_INVOKABLE CalendarItem* get(int index) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void countChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<CalendarItem*> m_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CALENDARITEMS_H
|
#endif // CALENDARITEMS_H
|
||||||
45
libnymea-common/types/repeatingoption.cpp
Normal file
45
libnymea-common/types/repeatingoption.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include "repeatingoption.h"
|
||||||
|
|
||||||
|
RepeatingOption::RepeatingOption(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RepeatingOption::RepeatingMode RepeatingOption::repeatingMode() const
|
||||||
|
{
|
||||||
|
return m_repeatingMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatingOption::setRepeatingMode(RepeatingOption::RepeatingMode repeatingMode)
|
||||||
|
{
|
||||||
|
if (m_repeatingMode != repeatingMode) {
|
||||||
|
m_repeatingMode = repeatingMode;
|
||||||
|
emit repeatingModeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList RepeatingOption::weekDays() const
|
||||||
|
{
|
||||||
|
return m_weekDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatingOption::setWeekDays(const QVariantList &weekDays)
|
||||||
|
{
|
||||||
|
if (m_weekDays != weekDays) {
|
||||||
|
m_weekDays = weekDays;
|
||||||
|
emit weekDaysChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList RepeatingOption::monthDays() const
|
||||||
|
{
|
||||||
|
return m_monthDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepeatingOption::setMonthDays(const QVariantList &monthDays)
|
||||||
|
{
|
||||||
|
if (m_monthDays != monthDays) {
|
||||||
|
m_monthDays = monthDays;
|
||||||
|
emit monthDaysChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
48
libnymea-common/types/repeatingoption.h
Normal file
48
libnymea-common/types/repeatingoption.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef REPEATINGOPTION_H
|
||||||
|
#define REPEATINGOPTION_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QVariantList>
|
||||||
|
|
||||||
|
class RepeatingOption: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(RepeatingMode repeatingMode READ repeatingMode WRITE setRepeatingMode NOTIFY repeatingModeChanged)
|
||||||
|
Q_PROPERTY(QVariantList weekDays READ weekDays WRITE setWeekDays NOTIFY weekDaysChanged)
|
||||||
|
Q_PROPERTY(QVariantList monthDays READ monthDays WRITE setMonthDays NOTIFY monthDaysChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum RepeatingMode {
|
||||||
|
RepeatingModeNone,
|
||||||
|
RepeatingModeHourly,
|
||||||
|
RepeatingModeDaily,
|
||||||
|
RepeatingModeWeekly,
|
||||||
|
RepeatingModeMonthly,
|
||||||
|
RepeatingModeYearly
|
||||||
|
};
|
||||||
|
Q_ENUM(RepeatingMode)
|
||||||
|
|
||||||
|
explicit RepeatingOption(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
RepeatingMode repeatingMode() const;
|
||||||
|
void setRepeatingMode(RepeatingMode repeatingMode);
|
||||||
|
|
||||||
|
QVariantList weekDays() const;
|
||||||
|
void setWeekDays(const QVariantList &weekDays);
|
||||||
|
|
||||||
|
QVariantList monthDays() const;
|
||||||
|
void setMonthDays(const QVariantList &monthDays);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void repeatingModeChanged();
|
||||||
|
void weekDaysChanged();
|
||||||
|
void monthDaysChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
RepeatingMode m_repeatingMode = RepeatingModeDaily;
|
||||||
|
QVariantList m_weekDays;
|
||||||
|
QVariantList m_monthDays;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // REPEATINGOPTION_H
|
||||||
@ -4,9 +4,16 @@
|
|||||||
#include "eventdescriptors.h"
|
#include "eventdescriptors.h"
|
||||||
#include "stateevaluator.h"
|
#include "stateevaluator.h"
|
||||||
#include "stateevaluators.h"
|
#include "stateevaluators.h"
|
||||||
|
#include "statedescriptor.h"
|
||||||
#include "ruleaction.h"
|
#include "ruleaction.h"
|
||||||
#include "ruleactions.h"
|
#include "ruleactions.h"
|
||||||
#include "timedescriptor.h"
|
#include "timedescriptor.h"
|
||||||
|
#include "timeeventitems.h"
|
||||||
|
#include "timeeventitem.h"
|
||||||
|
#include "calendaritems.h"
|
||||||
|
#include "calendaritem.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
Rule::Rule(const QUuid &id, QObject *parent) :
|
Rule::Rule(const QUuid &id, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
@ -14,9 +21,15 @@ Rule::Rule(const QUuid &id, QObject *parent) :
|
|||||||
m_eventDescriptors(new EventDescriptors(this)),
|
m_eventDescriptors(new EventDescriptors(this)),
|
||||||
// m_stateEvaluator(new StateEvaluator(this)),
|
// m_stateEvaluator(new StateEvaluator(this)),
|
||||||
m_actions(new RuleActions(this)),
|
m_actions(new RuleActions(this)),
|
||||||
m_exitActions(new RuleActions(this))
|
m_exitActions(new RuleActions(this)),
|
||||||
|
m_timeDescriptor(new TimeDescriptor(this))
|
||||||
{
|
{
|
||||||
|
qDebug() << "### Creating rule" << this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rule::~Rule()
|
||||||
|
{
|
||||||
|
qDebug() << "### Destroying rule" << this;
|
||||||
}
|
}
|
||||||
|
|
||||||
QUuid Rule::id() const
|
QUuid Rule::id() const
|
||||||
@ -113,11 +126,15 @@ Rule *Rule::clone() const
|
|||||||
for (int i = 0; i < this->eventDescriptors()->rowCount(); i++) {
|
for (int i = 0; i < this->eventDescriptors()->rowCount(); i++) {
|
||||||
ret->eventDescriptors()->addEventDescriptor(this->eventDescriptors()->get(i)->clone());
|
ret->eventDescriptors()->addEventDescriptor(this->eventDescriptors()->get(i)->clone());
|
||||||
}
|
}
|
||||||
// ret->stateEvaluator()->setStateDescriptor(this->stateEvaluator()->stateDescriptor()->clone());
|
for (int i = 0; i < this->timeDescriptor()->timeEventItems()->rowCount(); i++) {
|
||||||
// ret->stateEvaluator()->setStateOperator(this->stateEvaluator()->stateOperator());
|
ret->timeDescriptor()->timeEventItems()->addTimeEventItem(this->timeDescriptor()->timeEventItems()->get(i)->clone());
|
||||||
// for (int i = 0; i < this->stateEvaluator()->childEvaluators()->rowCount(); i++) {
|
}
|
||||||
// ret->stateEvaluator()->childEvaluators()->
|
for (int i = 0; i < this->timeDescriptor()->calendarItems()->rowCount(); i++) {
|
||||||
// }
|
ret->timeDescriptor()->calendarItems()->addCalendarItem(this->timeDescriptor()->calendarItems()->get(i)->clone());
|
||||||
|
}
|
||||||
|
if (this->stateEvaluator()) {
|
||||||
|
ret->setStateEvaluator(this->stateEvaluator()->clone());
|
||||||
|
}
|
||||||
for (int i = 0; i < this->actions()->rowCount(); i++) {
|
for (int i = 0; i < this->actions()->rowCount(); i++) {
|
||||||
ret->actions()->addRuleAction(this->actions()->get(i)->clone());
|
ret->actions()->addRuleAction(this->actions()->get(i)->clone());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ class Rule : public QObject
|
|||||||
Q_PROPERTY(TimeDescriptor* timeDescriptor READ timeDescriptor CONSTANT)
|
Q_PROPERTY(TimeDescriptor* timeDescriptor READ timeDescriptor CONSTANT)
|
||||||
public:
|
public:
|
||||||
explicit Rule(const QUuid &id = QUuid(), QObject *parent = nullptr);
|
explicit Rule(const QUuid &id = QUuid(), QObject *parent = nullptr);
|
||||||
|
~Rule();
|
||||||
|
|
||||||
QUuid id() const;
|
QUuid id() const;
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ public:
|
|||||||
|
|
||||||
Q_INVOKABLE void createStateEvaluator();
|
Q_INVOKABLE void createStateEvaluator();
|
||||||
|
|
||||||
Rule *clone() const;
|
Q_INVOKABLE Rule *clone() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void nameChanged();
|
void nameChanged();
|
||||||
|
|||||||
@ -59,3 +59,17 @@ StateEvaluator* StateEvaluator::addChildEvaluator()
|
|||||||
m_childEvaluators->addStateEvaluator(stateEvaluator);
|
m_childEvaluators->addStateEvaluator(stateEvaluator);
|
||||||
return stateEvaluator;
|
return stateEvaluator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StateEvaluator *StateEvaluator::clone() const
|
||||||
|
{
|
||||||
|
StateEvaluator *ret = new StateEvaluator();
|
||||||
|
ret->m_operator = this->m_operator;
|
||||||
|
ret->m_stateDescriptor->setDeviceId(this->m_stateDescriptor->deviceId());
|
||||||
|
ret->m_stateDescriptor->setStateTypeId(this->m_stateDescriptor->stateTypeId());
|
||||||
|
ret->m_stateDescriptor->setValueOperator(this->m_stateDescriptor->valueOperator());
|
||||||
|
ret->m_stateDescriptor->setValue(this->m_stateDescriptor->value());
|
||||||
|
for (int i = 0; i < this->m_childEvaluators->rowCount(); i++) {
|
||||||
|
ret->m_childEvaluators->addStateEvaluator(this->m_childEvaluators->get(i)->clone());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@ -33,6 +33,8 @@ public:
|
|||||||
|
|
||||||
Q_INVOKABLE StateEvaluator* addChildEvaluator();
|
Q_INVOKABLE StateEvaluator* addChildEvaluator();
|
||||||
|
|
||||||
|
StateEvaluator* clone() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void stateOperatorChanged();
|
void stateOperatorChanged();
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,20 @@
|
|||||||
#include "timedescriptor.h"
|
#include "timedescriptor.h"
|
||||||
|
|
||||||
|
#include "timeeventitems.h"
|
||||||
|
#include "calendaritems.h"
|
||||||
|
|
||||||
TimeDescriptor::TimeDescriptor(QObject *parent) : QObject(parent)
|
TimeDescriptor::TimeDescriptor(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
|
m_timeEventItems = new TimeEventItems(this);
|
||||||
|
m_calendarItems = new CalendarItems(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeEventItems *TimeDescriptor::timeEventItems() const
|
||||||
|
{
|
||||||
|
return m_timeEventItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
CalendarItems *TimeDescriptor::calendarItems() const
|
||||||
|
{
|
||||||
|
return m_calendarItems;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,15 +3,28 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
|
class TimeEventItems;
|
||||||
|
class CalendarItems;
|
||||||
|
|
||||||
class TimeDescriptor : public QObject
|
class TimeDescriptor : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(TimeEventItems* timeEventItems READ timeEventItems CONSTANT)
|
||||||
|
Q_PROPERTY(CalendarItems* calendarItems READ calendarItems CONSTANT)
|
||||||
public:
|
public:
|
||||||
explicit TimeDescriptor(QObject *parent = nullptr);
|
explicit TimeDescriptor(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
TimeEventItems* timeEventItems() const;
|
||||||
|
CalendarItems* calendarItems() const;
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
private:
|
||||||
|
TimeEventItems* m_timeEventItems = nullptr;
|
||||||
|
CalendarItems* m_calendarItems = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TIMEDESCRIPTOR_H
|
#endif // TIMEDESCRIPTOR_H
|
||||||
@ -1,8 +1,11 @@
|
|||||||
#include "timeeventitem.h"
|
#include "timeeventitem.h"
|
||||||
|
|
||||||
TimeEventItem::TimeEventItem(QObject *parent) : QObject(parent)
|
#include "repeatingoption.h"
|
||||||
{
|
|
||||||
|
|
||||||
|
TimeEventItem::TimeEventItem(QObject *parent):
|
||||||
|
QObject(parent),
|
||||||
|
m_repeatingOption(new RepeatingOption(this))
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime TimeEventItem::dateTime() const
|
QDateTime TimeEventItem::dateTime() const
|
||||||
@ -30,3 +33,17 @@ void TimeEventItem::setTime(const QTime &time)
|
|||||||
emit timeChanged();
|
emit timeChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RepeatingOption *TimeEventItem::repeatingOption() const
|
||||||
|
{
|
||||||
|
return m_repeatingOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeEventItem *TimeEventItem::clone() const
|
||||||
|
{
|
||||||
|
TimeEventItem* ret = new TimeEventItem();
|
||||||
|
ret->m_dateTime = this->m_dateTime;
|
||||||
|
ret->m_time = this->m_time;
|
||||||
|
ret->m_repeatingOption = this->m_repeatingOption;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@ -5,11 +5,14 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
|
|
||||||
|
class RepeatingOption;
|
||||||
|
|
||||||
class TimeEventItem : public QObject
|
class TimeEventItem : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged)
|
Q_PROPERTY(QDateTime dateTime READ dateTime WRITE setDateTime NOTIFY dateTimeChanged)
|
||||||
Q_PROPERTY(QTime time READ time WRITE setTime NOTIFY timeChanged)
|
Q_PROPERTY(QTime time READ time WRITE setTime NOTIFY timeChanged)
|
||||||
|
Q_PROPERTY(RepeatingOption* repeatingOption READ repeatingOption CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TimeEventItem(QObject *parent = nullptr);
|
explicit TimeEventItem(QObject *parent = nullptr);
|
||||||
@ -20,6 +23,10 @@ public:
|
|||||||
QTime time() const;
|
QTime time() const;
|
||||||
void setTime(const QTime &time);
|
void setTime(const QTime &time);
|
||||||
|
|
||||||
|
RepeatingOption* repeatingOption() const;
|
||||||
|
|
||||||
|
TimeEventItem* clone() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dateTimeChanged();
|
void dateTimeChanged();
|
||||||
void timeChanged();
|
void timeChanged();
|
||||||
@ -27,6 +34,7 @@ signals:
|
|||||||
private:
|
private:
|
||||||
QDateTime m_dateTime;
|
QDateTime m_dateTime;
|
||||||
QTime m_time;
|
QTime m_time;
|
||||||
|
RepeatingOption *m_repeatingOption = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,53 @@
|
|||||||
#include "timeeventitems.h"
|
#include "timeeventitems.h"
|
||||||
|
|
||||||
TimeEventItems::TimeEventItems(QObject *parent) : QObject(parent)
|
#include "timeeventitem.h"
|
||||||
|
|
||||||
|
TimeEventItems::TimeEventItems(QObject *parent):
|
||||||
|
QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TimeEventItems::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return m_list.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TimeEventItems::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeEventItems::addTimeEventItem(TimeEventItem *timeEventItem)
|
||||||
|
{
|
||||||
|
timeEventItem->setParent(this);
|
||||||
|
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||||
|
m_list.append(timeEventItem);
|
||||||
|
endInsertRows();
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeEventItems::removeTimeEventItem(int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index > m_list.count()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
beginRemoveRows(QModelIndex(), index, index);
|
||||||
|
m_list.takeAt(index)->deleteLater();
|
||||||
|
endRemoveRows();
|
||||||
|
emit countChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeEventItem *TimeEventItems::get(int index) const
|
||||||
|
{
|
||||||
|
if (index < 0 || index > m_list.count()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return m_list.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeEventItem *TimeEventItems::createNewTimeEventItem() const
|
||||||
|
{
|
||||||
|
return new TimeEventItem();
|
||||||
|
}
|
||||||
|
|||||||
@ -1,17 +1,32 @@
|
|||||||
#ifndef TIMEEVENTITEMS_H
|
#ifndef TIMEEVENTITEMS_H
|
||||||
#define TIMEEVENTITEMS_H
|
#define TIMEEVENTITEMS_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
class TimeEventItems : public QObject
|
class TimeEventItem;
|
||||||
|
|
||||||
|
class TimeEventItems: public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||||
public:
|
public:
|
||||||
explicit TimeEventItems(QObject *parent = nullptr);
|
TimeEventItems(QObject *parent);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
|
||||||
|
Q_INVOKABLE void addTimeEventItem(TimeEventItem *timeEventItem);
|
||||||
|
Q_INVOKABLE void removeTimeEventItem(int index);
|
||||||
|
|
||||||
|
Q_INVOKABLE TimeEventItem* get(int index) const;
|
||||||
|
Q_INVOKABLE TimeEventItem* createNewTimeEventItem() const;
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void countChanged();
|
||||||
|
|
||||||
public slots:
|
private:
|
||||||
|
QList<TimeEventItem*> m_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TIMEEVENTITEMS_H
|
#endif // TIMEEVENTITEMS_H
|
||||||
@ -13,7 +13,7 @@ win32:Debug:LIBS += -L$$top_builddir/libmea-core/debug \
|
|||||||
win32:Release:LIBS += -L$$top_builddir/libmea-core/release \
|
win32:Release:LIBS += -L$$top_builddir/libmea-core/release \
|
||||||
-L$$top_builddir/libnymea-common/release
|
-L$$top_builddir/libnymea-common/release
|
||||||
linux:!android:LIBS += -lavahi-client -lavahi-common
|
linux:!android:LIBS += -lavahi-client -lavahi-common
|
||||||
PRE_TARGETDEPS += ../libmea-core
|
PRE_TARGETDEPS += ../libmea-core ../libnymea-common
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
stylecontroller.h
|
stylecontroller.h
|
||||||
|
|
||||||
|
|||||||
@ -187,5 +187,16 @@
|
|||||||
<file>../LICENSE</file>
|
<file>../LICENSE</file>
|
||||||
<file>ui/images/Built_with_Qt_RGB_logo.svg</file>
|
<file>ui/images/Built_with_Qt_RGB_logo.svg</file>
|
||||||
<file>ui/images/Built_with_Qt_RGB_logo_vertical.svg</file>
|
<file>ui/images/Built_with_Qt_RGB_logo_vertical.svg</file>
|
||||||
|
<file>ui/magic/TimeEventDelegate.qml</file>
|
||||||
|
<file>ui/magic/EditTimeEventItemPage.qml</file>
|
||||||
|
<file>ui/magic/EventDescriptorDelegate.qml</file>
|
||||||
|
<file>ui/components/MeaDialog.qml</file>
|
||||||
|
<file>ui/magic/RuleActionDelegate.qml</file>
|
||||||
|
<file>ui/magic/EditCalendarItemPage.qml</file>
|
||||||
|
<file>ui/magic/CalendarItemDelegate.qml</file>
|
||||||
|
<file>ui/images/alarm-clock.svg</file>
|
||||||
|
<file>ui/images/action.svg</file>
|
||||||
|
<file>ui/images/event.svg</file>
|
||||||
|
<file>ui/images/state.svg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -23,20 +23,23 @@ Page {
|
|||||||
popup.open();
|
popup.open();
|
||||||
}
|
}
|
||||||
onCreateUserFailed: {
|
onCreateUserFailed: {
|
||||||
print("create user failed")
|
print("createUser failed")
|
||||||
var text
|
var message;
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case "UserErrorInvalidUserId":
|
case "UserErrorInvalidUserId":
|
||||||
text = qsTr("The email you've entered isn't valid.");
|
message = qsTr("The email you've entered isn't valid.")
|
||||||
|
break;
|
||||||
|
case "UserErrorDuplicateUserId":
|
||||||
|
message = qsTr("The email you've entered is already userd.")
|
||||||
break;
|
break;
|
||||||
case "UserErrorBadPassword":
|
case "UserErrorBadPassword":
|
||||||
text = qsTr("The password you've chose is too weak.");
|
message = qsTr("The password you've chose is too weak.")
|
||||||
|
break;
|
||||||
|
case "UserErrorBackendError":
|
||||||
|
message = qsTr("An error happened with the user storage. Please make sure your %1 box is installed correctly.")
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
text = qsTr("An error happened creating the user.");
|
|
||||||
}
|
}
|
||||||
// var popup = errorDialog.createObject(root, {title: qsTr("Error creating user"), text: text})
|
var popup = errorDialog.createObject(root, {text: message});
|
||||||
var popup = errorDialog.createObject(root, {title: "Error creating user", text: text})
|
|
||||||
popup.open();
|
popup.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,30 +13,45 @@ Page {
|
|||||||
HeaderButton {
|
HeaderButton {
|
||||||
imageSource: Qt.resolvedUrl("images/add.svg")
|
imageSource: Qt.resolvedUrl("images/add.svg")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var newRulePage = pageStack.push(Qt.resolvedUrl("magic/EditRulePage.qml"), {rule: Engine.ruleManager.createNewRule() });
|
d.editRulePage = pageStack.push(Qt.resolvedUrl("magic/EditRulePage.qml"), {rule: Engine.ruleManager.createNewRule() });
|
||||||
newRulePage.onAccept.connect(function() {
|
d.editRulePage.StackView.onRemoved.connect(function() {
|
||||||
Engine.ruleManager.addRule(newRulePage.rule);
|
d.editRulePage.rule.destroy()
|
||||||
|
d.editRulePage = null;
|
||||||
|
})
|
||||||
|
d.editRulePage.onAccept.connect(function() {
|
||||||
|
d.editRulePage.busy = true;
|
||||||
|
Engine.ruleManager.addRule(d.editRulePage.rule);
|
||||||
|
})
|
||||||
|
d.editRulePage.onCancel.connect(function() {
|
||||||
|
pageStack.pop();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
property var editRulePage: null
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: Engine.ruleManager
|
target: Engine.ruleManager
|
||||||
onAddRuleReply: {
|
onAddRuleReply: {
|
||||||
|
d.editRulePage.busy = false;
|
||||||
if (ruleError == "RuleErrorNoError") {
|
if (ruleError == "RuleErrorNoError") {
|
||||||
pageStack.pop();
|
pageStack.pop();
|
||||||
} else {
|
} else {
|
||||||
var popup = errorDialog.createObject(root, {text: ruleError })
|
var popup = errorDialog.createObject(app, {errorCode: ruleError })
|
||||||
popup.open();
|
popup.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditRuleReply: {
|
onEditRuleReply: {
|
||||||
|
d.editRulePage.busy = false;
|
||||||
if (ruleError == "RuleErrorNoError") {
|
if (ruleError == "RuleErrorNoError") {
|
||||||
pageStack.pop();
|
pageStack.pop();
|
||||||
} else {
|
} else {
|
||||||
var popup = errorDialog.createObject(root, {text: ruleError })
|
var popup = errorDialog.createObject(app, {errorCode: ruleError })
|
||||||
popup.open();
|
popup.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,10 +81,18 @@ Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var editRulePage = pageStack.push(Qt.resolvedUrl("magic/EditRulePage.qml"), {rule: Engine.ruleManager.rules.get(index) })
|
d.editRulePage = pageStack.push(Qt.resolvedUrl("magic/EditRulePage.qml"), {rule: Engine.ruleManager.rules.get(index).clone()})
|
||||||
editRulePage.onAccept.connect(function() {
|
d.editRulePage.StackView.onRemoved.connect(function() {
|
||||||
|
d.editRulePage.rule.destroy();
|
||||||
|
d.editRulePage = null
|
||||||
|
})
|
||||||
|
d.editRulePage.onAccept.connect(function() {
|
||||||
|
d.editRulePage.busy = true;
|
||||||
Engine.ruleManager.editRule(editRulePage.rule);
|
Engine.ruleManager.editRule(editRulePage.rule);
|
||||||
})
|
})
|
||||||
|
d.editRulePage.onCancel.connect(function() {
|
||||||
|
pageStack.pop();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
swipe.right: MouseArea {
|
swipe.right: MouseArea {
|
||||||
|
|||||||
@ -22,6 +22,8 @@ ApplicationWindow {
|
|||||||
property int iconSize: 30
|
property int iconSize: 30
|
||||||
property int delegateHeight: 60
|
property int delegateHeight: 60
|
||||||
|
|
||||||
|
property bool landscape: app.width > app.height
|
||||||
|
|
||||||
property var settings: Settings {
|
property var settings: Settings {
|
||||||
property string lastConnectedHost: ""
|
property string lastConnectedHost: ""
|
||||||
property int viewMode: ApplicationWindow.Maximized
|
property int viewMode: ApplicationWindow.Maximized
|
||||||
|
|||||||
@ -38,8 +38,9 @@ Page {
|
|||||||
target: networkManger.manager
|
target: networkManger.manager
|
||||||
onErrorOccured: {
|
onErrorOccured: {
|
||||||
print("Error occured", errorMessage)
|
print("Error occured", errorMessage)
|
||||||
errorDialog.errorText = errorMessage
|
var errorDialog = Qt.createComponent(Qt.resolvedUrl("components/ErrorDialog.qml"));
|
||||||
errorDialog.open()
|
var popup = errorDialog.createObject(app, {text: errorMessage})
|
||||||
|
popup.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
onWirelessStatusChanged: {
|
onWirelessStatusChanged: {
|
||||||
@ -287,28 +288,6 @@ Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Dialog {
|
|
||||||
id: errorDialog
|
|
||||||
width: Math.min(parent.width * .9, 400)
|
|
||||||
x: (parent.width - width) / 2
|
|
||||||
y: (parent.height - height) / 2
|
|
||||||
standardButtons: Dialog.Ok
|
|
||||||
|
|
||||||
property string errorText
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors { left: parent.left; right: parent.right; top: parent.top }
|
|
||||||
spacing: app.margins
|
|
||||||
|
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
text: errorDialog.errorText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: settingsPage
|
id: settingsPage
|
||||||
|
|
||||||
|
|||||||
@ -2,51 +2,15 @@ import QtQuick 2.8
|
|||||||
import QtQuick.Controls 2.1
|
import QtQuick.Controls 2.1
|
||||||
import QtQuick.Layouts 1.2
|
import QtQuick.Layouts 1.2
|
||||||
|
|
||||||
Dialog {
|
MeaDialog {
|
||||||
id: root
|
id: root
|
||||||
width: Math.min(parent.width * .8, contentLabel.implicitWidth)
|
|
||||||
x: (parent.width - width) / 2
|
|
||||||
y: (parent.height - height) / 2
|
|
||||||
modal: true
|
|
||||||
|
|
||||||
title: qsTr("Error")
|
title: qsTr("Oh snap!")
|
||||||
property alias text: contentLabel.text
|
headerIcon: "../images/dialog-error-symbolic.svg"
|
||||||
|
|
||||||
standardButtons: Dialog.Ok
|
property string errorCode: ""
|
||||||
|
|
||||||
header: Item {
|
text: qsTr("An unexpected error happened. We're sorry for that.") +
|
||||||
implicitHeight: headerRow.height + app.margins * 2
|
(errorCode.length > 0 ? "\n\n" + qsTr("Error code: %1").arg(errorCode) : "")
|
||||||
implicitWidth: parent.width
|
|
||||||
RowLayout {
|
|
||||||
id: headerRow
|
|
||||||
anchors { left: parent.left; right: parent.right; top: parent.top; margins: app.margins }
|
|
||||||
spacing: app.margins
|
|
||||||
ColorIcon {
|
|
||||||
Layout.preferredHeight: app.iconSize * 2
|
|
||||||
Layout.preferredWidth: height
|
|
||||||
name: "../images/dialog-error-symbolic.svg"
|
|
||||||
color: app.guhAccent
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: titleLabel
|
|
||||||
Layout.fillWidth: true
|
|
||||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
|
||||||
text: root.title
|
|
||||||
color: app.guhAccent
|
|
||||||
font.pixelSize: app.largeFont
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: content
|
|
||||||
anchors { left: parent.left; top: parent.top; right: parent.right }
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: contentLabel
|
|
||||||
Layout.fillWidth: true
|
|
||||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
54
mea/ui/components/MeaDialog.qml
Normal file
54
mea/ui/components/MeaDialog.qml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import QtQuick 2.8
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
|
||||||
|
Dialog {
|
||||||
|
id: root
|
||||||
|
width: Math.min(parent.width * .8, Math.max(contentLabel.implicitWidth, 400))
|
||||||
|
x: (parent.width - width) / 2
|
||||||
|
y: (parent.height - height) / 2
|
||||||
|
|
||||||
|
property alias headerIcon: headerColorIcon.name
|
||||||
|
property alias text: contentLabel.text
|
||||||
|
default property alias children: content.children
|
||||||
|
|
||||||
|
standardButtons: Dialog.Ok
|
||||||
|
|
||||||
|
header: Item {
|
||||||
|
implicitHeight: headerRow.height + app.margins * 2
|
||||||
|
implicitWidth: parent.width
|
||||||
|
RowLayout {
|
||||||
|
id: headerRow
|
||||||
|
anchors { left: parent.left; right: parent.right; top: parent.top; margins: app.margins }
|
||||||
|
spacing: app.margins
|
||||||
|
ColorIcon {
|
||||||
|
id: headerColorIcon
|
||||||
|
Layout.preferredHeight: app.iconSize * 2
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
color: app.guhAccent
|
||||||
|
visible: name.length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: titleLabel
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: app.margins
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
text: root.title
|
||||||
|
color: app.guhAccent
|
||||||
|
font.pixelSize: app.largeFont
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ColumnLayout {
|
||||||
|
id: content
|
||||||
|
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: contentLabel
|
||||||
|
Layout.fillWidth: true
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
visible: text.length > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,60 +39,72 @@ Item {
|
|||||||
model: logsModel
|
model: logsModel
|
||||||
clip: true
|
clip: true
|
||||||
onCountChanged: positionViewAtEnd()
|
onCountChanged: positionViewAtEnd()
|
||||||
delegate: ItemDelegate {
|
delegate: SwipeDelegate {
|
||||||
|
id: logEntryDelegate
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
implicitHeight: app.delegateHeight
|
||||||
contentItem: RowLayout {
|
contentItem: RowLayout {
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
name: "../images/event.svg"
|
||||||
|
color: app.guhAccent
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Label {
|
||||||
RowLayout {
|
id: timeStampLabel
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
text: Qt.formatDateTime(model.timestamp,"dd.MM.yy - hh:mm:ss")
|
||||||
ColorIcon {
|
|
||||||
Layout.preferredHeight: timeStampLabel.height
|
|
||||||
Layout.preferredWidth: height
|
|
||||||
name: "../images/clock-app-symbolic.svg"
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: timeStampLabel
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: Qt.formatDateTime(model.timestamp,"dd.MM.yy - hh:mm:ss")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RowLayout {
|
Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Label {
|
text: qsTr("Data: %1").arg(model.value.trim())
|
||||||
text: qsTr("Data:")
|
elide: Text.ElideRight
|
||||||
}
|
font.pixelSize: app.smallFont
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: model.value.trim()
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeaderButton {
|
// ColorIcon {
|
||||||
imageSource: "../images/magic.svg"
|
// Layout.preferredWidth: app.iconSize
|
||||||
color: {
|
// Layout.preferredHeight: width
|
||||||
for (var i = 0; i < rulesFilterModel.count; i++) {
|
// name: "../images/magic.svg"
|
||||||
var rule = rulesFilterModel.get(i);
|
// color: {
|
||||||
for (var j = 0; j < rule.eventDescriptors.count; j++) {
|
// for (var i = 0; i < rulesFilterModel.count; i++) {
|
||||||
var eventDescriptor = rule.eventDescriptors.get(j);
|
// var rule = rulesFilterModel.get(i);
|
||||||
if (eventDescriptor.eventTypeId === root.logsModel.typeId) {
|
// for (var j = 0; j < rule.eventDescriptors.count; j++) {
|
||||||
var matching = true;
|
// var eventDescriptor = rule.eventDescriptors.get(j);
|
||||||
for (var k = 0; k < eventDescriptor.paramDescriptors.count; k++) {
|
// if (eventDescriptor.eventTypeId === root.logsModel.typeId) {
|
||||||
var paramDescriptor = eventDescriptor.paramDescriptors.get(k);
|
// var matching = true;
|
||||||
if (paramDescriptor.value === model.value) {
|
// for (var k = 0; k < eventDescriptor.paramDescriptors.count; k++) {
|
||||||
return app.guhAccent;
|
// var paramDescriptor = eventDescriptor.paramDescriptors.get(k);
|
||||||
}
|
// if (paramDescriptor.value === model.value) {
|
||||||
}
|
// return app.guhAccent;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return keyColor;
|
// }
|
||||||
}
|
// }
|
||||||
|
// return keyColor;
|
||||||
|
// }
|
||||||
|
|
||||||
onClicked: root.addRuleClicked(model.value)
|
// }
|
||||||
|
}
|
||||||
|
swipe.right: MouseArea {
|
||||||
|
height: logEntryDelegate.height
|
||||||
|
width: height
|
||||||
|
anchors.right: parent.right
|
||||||
|
ColorIcon {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: app.margins
|
||||||
|
name: "../images/magic.svg"
|
||||||
|
}
|
||||||
|
onClicked: root.addRuleClicked(model.value)
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
if (swipe.complete) {
|
||||||
|
swipe.close()
|
||||||
|
} else {
|
||||||
|
swipe.open(SwipeDelegate.Right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,7 +51,7 @@ Page {
|
|||||||
popup.open();
|
popup.open();
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
var popup = errorDialog.createObject(root, {text: qsTr("Remove device error: %1").arg(JSON.stringify(params.deviceError)) })
|
var popup = errorDialog.createObject(root, {errorCode: params.deviceError})
|
||||||
popup.open();
|
popup.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
172
mea/ui/images/action.svg
Normal file
172
mea/ui/images/action.svg
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="96"
|
||||||
|
height="96"
|
||||||
|
id="svg4874"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||||
|
viewBox="0 0 96 96.000001"
|
||||||
|
sodipodi:docname="action.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4876" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="14.049998"
|
||||||
|
inkscape:cx="54.082123"
|
||||||
|
inkscape:cy="46.974137"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
showborder="true"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:object-nodes="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:snap-global="true"
|
||||||
|
inkscape:window-width="2880"
|
||||||
|
inkscape:window-height="1698"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="44"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid5451"
|
||||||
|
empspacing="8" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="8,-8.0000001"
|
||||||
|
id="guide4063"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="4,-8.0000001"
|
||||||
|
id="guide4065"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,88.000001"
|
||||||
|
id="guide4067"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,92.000001"
|
||||||
|
id="guide4069"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="104,4"
|
||||||
|
id="guide4071"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-5,8.0000001"
|
||||||
|
id="guide4073"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="88,-8.0000001"
|
||||||
|
id="guide4077"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,84.000001"
|
||||||
|
id="guide4074"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="12,-8.0000001"
|
||||||
|
id="guide4076"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="84,-8.0000001"
|
||||||
|
id="guide4080"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="48,-8.0000001"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide4170"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="-8,48"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide4172"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="92,-8.0000001"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide4760"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata4879">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(67.857146,-78.50504)">
|
||||||
|
<rect
|
||||||
|
transform="rotate(90)"
|
||||||
|
y="-28.142855"
|
||||||
|
x="78.505043"
|
||||||
|
height="96"
|
||||||
|
width="96"
|
||||||
|
id="rect4782-637"
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:3.99999976;marker:none;enable-background:accumulate" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="rect4747-4"
|
||||||
|
d="m 18.142883,124.50503 1.000025,3.99998 h -32.999999 v -3.99998 z"
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;stroke:none;stroke-width:8.99999905;marker:none;enable-background:accumulate"
|
||||||
|
inkscape:transform-center-x="-26.500014" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="M 5.6230724,101.05661 C -4.6712646,90.767855 -20.167327,87.685805 -33.61715,93.253885 c -13.44979,5.56807 -22.23047,18.700765 -22.23047,33.251945 0,14.55118 8.78068,27.68194 22.23047,33.25002 13.449823,5.56804 28.9458854,2.48602 39.2402224,-7.80276 l -2.828107,-2.82811 c -9.158173,9.15322 -22.9166364,11.88745 -34.8828054,6.93358 -11.96618,-4.95383 -19.75979,-16.60879 -19.75979,-29.55273 0,-12.94393 7.79361,-24.60083 19.75979,-29.554705 11.966169,-4.95382 25.7246324,-2.2196 34.8828054,6.933635 z"
|
||||||
|
id="path4145"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5837"
|
||||||
|
d="m 5.1430854,114.50443 0.0076,24 c 3.6500406,-1.66873 7.3659206,-3.53593 11.1491896,-5.59872 3.747742,-2.06778 7.362822,-4.2005 10.84286,-6.40026 -3.480038,-2.15576 -7.095118,-4.26806 -10.84286,-6.33584 -3.785348,-2.06393 -7.503345,-3.95188 -11.1553126,-5.66518 z"
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.99940658;marker:none;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.0 KiB |
197
mea/ui/images/alarm-clock.svg
Normal file
197
mea/ui/images/alarm-clock.svg
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="96"
|
||||||
|
height="96"
|
||||||
|
id="svg4874"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.91+devel r"
|
||||||
|
viewBox="0 0 96 96.000001"
|
||||||
|
sodipodi:docname="reminder.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4876" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="5.6199993"
|
||||||
|
inkscape:cx="4.0836252"
|
||||||
|
inkscape:cy="58.033793"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="g4780"
|
||||||
|
showgrid="true"
|
||||||
|
showborder="true"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:object-nodes="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid5451"
|
||||||
|
empspacing="8" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="8,-8.0000001"
|
||||||
|
id="guide4063" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="4,-8.0000001"
|
||||||
|
id="guide4065" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,88.000001"
|
||||||
|
id="guide4067" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,92.000001"
|
||||||
|
id="guide4069" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="104,4"
|
||||||
|
id="guide4071" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-5,8.0000001"
|
||||||
|
id="guide4073" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="92,-8.0000001"
|
||||||
|
id="guide4075" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="88,-8.0000001"
|
||||||
|
id="guide4077" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,84.000001"
|
||||||
|
id="guide4074" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="12,-8.0000001"
|
||||||
|
id="guide4076" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-5,12"
|
||||||
|
id="guide4078" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="84,-9.0000001"
|
||||||
|
id="guide4080" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="48,-8.0000001"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide4170" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="-8,48"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide4172" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata4879">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(67.857146,-78.50504)">
|
||||||
|
<g
|
||||||
|
transform="matrix(0,-1,-1,0,373.50506,516.50504)"
|
||||||
|
id="g4845"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
inkscape:export-ydpi="90"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-filename="next01.png"
|
||||||
|
transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
|
||||||
|
id="g4778"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<g
|
||||||
|
transform="matrix(-1,0,0,1,575.99999,611)"
|
||||||
|
id="g4780"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
|
||||||
|
id="rect4782"
|
||||||
|
width="96.037987"
|
||||||
|
height="96"
|
||||||
|
x="-438.00244"
|
||||||
|
y="345.36221"
|
||||||
|
transform="scale(-1,1)" />
|
||||||
|
<path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="m 364.0904,368.96573 c -0.0215,-0.0161 -0.0354,-0.0404 -0.0567,-0.0566 -0.0253,-0.0201 -0.057,-0.0305 -0.0821,-0.0508 z"
|
||||||
|
id="path4157" />
|
||||||
|
<path
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#808080;fill-opacity:1;stroke:none"
|
||||||
|
d="m 364.07673,417.80167 -0.13873,0.10742 c 0.0251,-0.0203 0.0569,-0.0307 0.0821,-0.0508 0.0214,-0.0162 0.0353,-0.0405 0.0567,-0.0566 z"
|
||||||
|
id="path4344" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:normal;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 417.99454,395.36222 -3.75148,0 -22.5089,0 -3.75149,0 0,-3.99941 3.75149,0 22.5089,0 3.75148,0 0,3.99941 z"
|
||||||
|
id="path5329"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:normal;font-family:sans-serif;-inkscape-font-specification:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 391.98425,395.36222 -4.00329,0 0,-3.7143 0,-18.57141 0,-3.71429 4.00329,0 0,3.71429 0,18.57141 0,3.7143 z"
|
||||||
|
id="path5331"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079107;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 432,393.36133 c 0,23.17267 -18.83507,42 -42.01562,42 -23.18056,0 -42.01758,-18.82733 -42.01758,-42 0,-23.17267 18.83702,-42 42.01758,-42 23.18055,0 42.01562,18.82733 42.01562,42 z m -4.00195,0 c 0,-21.00963 -16.99445,-37.99805 -38.01367,-37.99805 -21.01923,0 -38.01563,16.98842 -38.01563,37.99805 0,21.00963 16.9964,38 38.01563,38 21.01922,0 38.01367,-16.99037 38.01367,-38 z"
|
||||||
|
id="path4151"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
inkscape:transform-center-y="-28.541779"
|
||||||
|
sodipodi:nodetypes="zscccsz"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4187"
|
||||||
|
d="m 427.05076,356.30961 c 9.26681,9.26315 9.26681,13.89473 0,23.15787 l -0.8205,0.82018 c -1.47358,-5.56141 -4.38677,-10.63666 -8.44632,-14.71491 -4.0766,-4.05955 -9.15035,-6.97497 -14.71167,-8.45201 l 0.81144,-0.81113 c 9.26682,-9.26316 13.90023,-9.26316 23.16705,0 z"
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;stroke:none;stroke-width:9;marker:none;enable-background:accumulate"
|
||||||
|
inkscape:transform-center-x="-28.537261" />
|
||||||
|
<path
|
||||||
|
inkscape:transform-center-x="28.541784"
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;stroke:none;stroke-width:9;marker:none;enable-background:accumulate"
|
||||||
|
d="m 427.05076,430.41481 c -9.26682,9.26316 -13.90023,9.26316 -23.16705,0 l -0.82049,-0.82018 c 5.56361,-1.47299 10.64087,-4.38503 14.72072,-8.44297 4.06116,-4.07499 6.97774,-9.14674 8.45537,-14.70585 l 0.81145,0.81112 c 9.26681,9.26315 9.26681,13.89473 0,23.15788 z"
|
||||||
|
id="path4085"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="zscccsz"
|
||||||
|
inkscape:transform-center-y="-28.537254" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 10 KiB |
180
mea/ui/images/event.svg
Normal file
180
mea/ui/images/event.svg
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="96"
|
||||||
|
height="96"
|
||||||
|
id="svg4874"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||||
|
viewBox="0 0 96 96.000001"
|
||||||
|
sodipodi:docname="event.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4876" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="28.099996"
|
||||||
|
inkscape:cx="22.257505"
|
||||||
|
inkscape:cy="41.601488"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
showborder="true"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:bbox-paths="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:snap-bbox-edge-midpoints="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:object-paths="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
inkscape:object-nodes="true"
|
||||||
|
inkscape:snap-smooth-nodes="true"
|
||||||
|
inkscape:snap-midpoints="true"
|
||||||
|
inkscape:snap-object-midpoints="true"
|
||||||
|
inkscape:snap-center="true"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:snap-global="true"
|
||||||
|
inkscape:window-width="2880"
|
||||||
|
inkscape:window-height="1698"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="44"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid5451"
|
||||||
|
empspacing="8" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="8,-8.0000001"
|
||||||
|
id="guide4063"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="4,-8.0000001"
|
||||||
|
id="guide4065"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,88.000001"
|
||||||
|
id="guide4067"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,92.000001"
|
||||||
|
id="guide4069"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="104,4"
|
||||||
|
id="guide4071"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-5,8.0000001"
|
||||||
|
id="guide4073"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="88,-8.0000001"
|
||||||
|
id="guide4077"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-8,84.000001"
|
||||||
|
id="guide4074"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="12,-8.0000001"
|
||||||
|
id="guide4076"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="84,-8.0000001"
|
||||||
|
id="guide4080"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="48,-8.0000001"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide4170"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="-8,48"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide4172"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="92,-8.0000001"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide4760"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata4879">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(67.857146,-78.50504)">
|
||||||
|
<rect
|
||||||
|
transform="rotate(90)"
|
||||||
|
y="-28.142855"
|
||||||
|
x="78.505043"
|
||||||
|
height="96"
|
||||||
|
width="96"
|
||||||
|
id="rect4782-637"
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:3.99999976;marker:none;enable-background:accumulate" />
|
||||||
|
<g
|
||||||
|
id="g842"
|
||||||
|
transform="matrix(-1,0,0,1,-39.714411,2.025e-5)">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4145"
|
||||||
|
d="M 5.6230724,101.05661 C -4.6712646,90.767855 -20.167327,87.685805 -33.61715,93.253885 c -13.44979,5.56807 -22.23047,18.700765 -22.23047,33.251945 0,14.55118 8.78068,27.68194 22.23047,33.25002 13.449823,5.56804 28.9458854,2.48602 39.2402224,-7.80276 l -2.828107,-2.82811 c -9.158173,9.15322 -22.9166364,11.88745 -34.8828054,6.93358 -11.96618,-4.95383 -19.75979,-16.60879 -19.75979,-29.55273 0,-12.94393 7.79361,-24.60083 19.75979,-29.554705 11.966169,-4.95382 25.7246324,-2.2196 34.8828054,6.933635 z"
|
||||||
|
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.99999976;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<g
|
||||||
|
transform="matrix(-1,0,0,1,13.285644,0)"
|
||||||
|
id="g836">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="rect4747-4"
|
||||||
|
d="m 18.142883,124.50503 1.000025,3.99998 h -32.999999 v -3.99998 z"
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#808080;fill-opacity:1;stroke:none;stroke-width:8.99999905;marker:none;enable-background:accumulate"
|
||||||
|
inkscape:transform-center-x="-26.500014" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5837"
|
||||||
|
d="m 5.1430854,114.50443 0.0076,24 c 3.6500406,-1.66873 7.3659206,-3.53593 11.1491896,-5.59872 3.747742,-2.06778 7.362822,-4.2005 10.84286,-6.40026 -3.480038,-2.15576 -7.095118,-4.26806 -10.84286,-6.33584 -3.785348,-2.06393 -7.503345,-3.95188 -11.1553126,-5.66518 z"
|
||||||
|
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.99940658;marker:none;enable-background:accumulate" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.3 KiB |
19
mea/ui/images/state.svg
Normal file
19
mea/ui/images/state.svg
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg id="svg4874" width="96" height="96" version="1.1" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||||
|
<metadata id="metadata4879">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||||
|
<dc:title/>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g id="layer1" transform="translate(67.857 -78.505)">
|
||||||
|
<rect id="rect4782-2" transform="rotate(90)" x="78.505" y="-28.143" width="96" height="96" style="color:#000000;fill:none"/>
|
||||||
|
<path id="path4643-2" d="m-39.869 98.504-0.01134 2e-3c-5.0328 0.0582-8.7136-0.12019-11.725 1.541-1.5055 0.83062-2.6968 2.2356-3.3555 3.9902-0.65866 1.7546-0.89647 3.8364-0.89647 6.4668v48.002c0 2.6304 0.23773 4.7122 0.89647 6.4668 0.65866 1.7546 1.85 3.1596 3.3555 3.9902 3.011 1.6613 6.6918 1.4848 11.725 1.543h0.01134 40.023 0.01134c5.0328-0.0582 8.7136 0.1183 11.725-1.543 1.5055-0.83066 2.6968-2.2356 3.3555-3.9902 0.65866-1.7546 0.8965-3.8364 0.8965-6.4668v-48.002c0-2.6304-0.23773-4.7122-0.8965-6.4668-0.65866-1.7547-1.85-3.1596-3.3555-3.9902-3.011-1.6613-6.6918-1.4829-11.725-1.5411l-0.01134-2e-3 -12.012 2e-3v4l11.977-2e-3c5.0542 0.0586 8.3726 0.23547 9.8398 1.0449 0.73364 0.40479 1.1527 0.85493 1.543 1.8945 0.39024 1.0396 0.64059 2.691 0.64059 5.0606v48.002c0 2.3695-0.2502 4.0209-0.64059 5.0605-0.39027 1.0396-0.80935 1.4898-1.543 1.8945-1.4645 0.80806-4.7782 0.98615-9.8164 1.0449h-39.977-0.02268c-5.0383-0.059-8.3519-0.23697-9.8164-1.0449-0.73364-0.40475-1.1508-0.85489-1.541-1.8945-0.39027-1.0396-0.6426-2.691-0.6426-5.0605v-48.002c0-2.3696 0.25247-4.0209 0.6426-5.0606 0.39024-1.0396 0.80734-1.4897 1.541-1.8945 1.4645-0.80807 4.7782-0.98616 9.8164-1.0449l12 2e-3v-4z" style="color-rendering:auto;color:#000000;fill:#808080;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;image-rendering:auto;isolation:auto;mix-blend-mode:normal;shape-padding:0;shape-rendering:auto;solid-color:#000000;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
|
||||||
|
<path id="path4237" d="m-21.858 82.505v50h4v-50z" style="fill:#808080"/>
|
||||||
|
<path id="path5588-9-2-96-04" d="m-7.8571 124.51-24 8e-3c1.6687 3.6501 3.5359 7.366 5.5987 11.149 2.0678 3.7477 4.2005 7.3628 6.4003 10.843 2.1557-3.48 4.268-7.0951 6.3358-10.843 2.0639-3.7854 3.9519-7.5033 5.6652-11.155z" style="color:#000000;fill:#808080"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.7 KiB |
111
mea/ui/magic/CalendarItemDelegate.qml
Normal file
111
mea/ui/magic/CalendarItemDelegate.qml
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import Mea 1.0
|
||||||
|
import "../components"
|
||||||
|
|
||||||
|
SwipeDelegate {
|
||||||
|
id: root
|
||||||
|
implicitHeight: app.delegateHeight
|
||||||
|
|
||||||
|
property var calendarItem: null
|
||||||
|
|
||||||
|
readonly property bool isDateBased: calendarItem.repeatingOption.repeatingMode === RepeatingOption.RepeatingModeNone ||
|
||||||
|
calendarItem.repeatingOption.repeatingMode === RepeatingOption.RepeatingModeYearly
|
||||||
|
|
||||||
|
signal removeCalendarItem();
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: app.margins
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
name: "../images/clock-app-symbolic.svg"
|
||||||
|
color: app.guhAccent
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: qsTr("From %1 to %2")
|
||||||
|
.arg(root.isDateBased ? Qt.formatDateTime(root.calendarItem.dateTime) : Qt.formatTime(root.calendarItem.startTime))
|
||||||
|
.arg(root.isDateBased ? Qt.formatDateTime(new Date(root.calendarItem.dateTime.getTime() + root.calendarItem.duration * 60000)) : Qt.formatTime(new Date(root.calendarItem.startTime.getTime() + root.calendarItem.duration * 60000)))
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pixelSize: app.smallFont
|
||||||
|
text: qsTr("repeated %3")
|
||||||
|
.arg(repeatingString)
|
||||||
|
|
||||||
|
property string repeatingString: {
|
||||||
|
switch (root.calendarItem.repeatingOption.repeatingMode) {
|
||||||
|
case RepeatingOption.RepeatingModeNone:
|
||||||
|
return qsTr("never");
|
||||||
|
case RepeatingOption.RepeatingModeHourly:
|
||||||
|
return qsTr("hourly");
|
||||||
|
case RepeatingOption.RepeatingModeDaily:
|
||||||
|
return qsTr("daily");
|
||||||
|
case RepeatingOption.RepeatingModeWeekly:
|
||||||
|
var weekdays = []
|
||||||
|
for (var i = 0; i < root.calendarItem.repeatingOption.weekDays.length; i++) {
|
||||||
|
switch (root.calendarItem.repeatingOption.weekDays[i]) {
|
||||||
|
case 1:
|
||||||
|
weekdays.push(qsTr("Mon"));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
weekdays.push(qsTr("Tue"));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
weekdays.push(qsTr("Wed"));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
weekdays.push(qsTr("Thu"));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
weekdays.push(qsTr("Fri"));
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
weekdays.push(qsTr("Sat"));
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
weekdays.push(qsTr("Sun"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qsTr("weekly on %1").arg(weekdays.join(', '));
|
||||||
|
case RepeatingOption.RepeatingModeMonthly:
|
||||||
|
return qsTr("monthly on the %1").arg(root.calendarItem.repeatingOption.monthDays.join(', '));
|
||||||
|
case RepeatingOption.RepeatingModeYearly:
|
||||||
|
return qsTr("every year");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swipe.right: MouseArea {
|
||||||
|
height: root.height
|
||||||
|
width: height
|
||||||
|
anchors.right: parent.right
|
||||||
|
ColorIcon {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: app.margins
|
||||||
|
name: "../images/delete.svg"
|
||||||
|
color: "red"
|
||||||
|
}
|
||||||
|
onClicked: root.removeCalendarItem()
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
var page = pageStack.push(Qt.resolvedUrl("EditCalendarItemPage.qml"), {calendarItem: root.calendarItem})
|
||||||
|
page.onBackPressed.connect(function() {pageStack.pop()})
|
||||||
|
page.onDone.connect(function() {
|
||||||
|
pageStack.pop()
|
||||||
|
print("calendarItem.time is now", root.calendarItem.time)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,14 +21,23 @@ Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rule is optional and might be initialized with anything wanted. A new, empty one will be created if null
|
// Rule is optional and might be initialized with anything wanted. A new, empty one will be created if null
|
||||||
|
// This Page will take ownership of the rule and delete it eventually.
|
||||||
function addRule(rule) {
|
function addRule(rule) {
|
||||||
if (rule === null || rule === undefined) {
|
if (rule === null || rule === undefined) {
|
||||||
rule = Engine.ruleManager.createNewRule();
|
rule = Engine.ruleManager.createNewRule();
|
||||||
}
|
}
|
||||||
var page = pageStack.push(Qt.resolvedUrl("EditRulePage.qml"), {rule: rule});
|
d.editRulePage = pageStack.push(Qt.resolvedUrl("EditRulePage.qml"), {rule: rule});
|
||||||
page.onAccept.connect(function() {
|
d.editRulePage.StackView.onRemoved.connect(function() {
|
||||||
|
d.editRulePage.rule.destroy();
|
||||||
|
d.editRulePage = null
|
||||||
|
})
|
||||||
|
d.editRulePage.onAccept.connect(function() {
|
||||||
|
d.editRulePage.busy = true;
|
||||||
Engine.ruleManager.addRule(page.rule);
|
Engine.ruleManager.addRule(page.rule);
|
||||||
})
|
})
|
||||||
|
d.editRulePage.onCancel.connect(function() {
|
||||||
|
pageStack.pop();
|
||||||
|
})
|
||||||
|
|
||||||
// if (rule.eventDescriptors.count === 0) {
|
// if (rule.eventDescriptors.count === 0) {
|
||||||
// var eventDescriptor = rule.eventDescriptors.createNewEventDescriptor();
|
// var eventDescriptor = rule.eventDescriptors.createNewEventDescriptor();
|
||||||
@ -38,18 +47,32 @@ Page {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
property var editRulePage: null
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: Engine.ruleManager
|
target: Engine.ruleManager
|
||||||
onAddRuleReply: {
|
onAddRuleReply: {
|
||||||
|
d.editRulePage.busy = false;
|
||||||
if (ruleError == "RuleErrorNoError") {
|
if (ruleError == "RuleErrorNoError") {
|
||||||
pageStack.pop();
|
pageStack.pop();
|
||||||
|
} else {
|
||||||
|
var errorDialog = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml"));
|
||||||
|
var popup = errorDialog.createObject(root, {errorCode: ruleError })
|
||||||
|
popup.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditRuleReply: {
|
onEditRuleReply: {
|
||||||
print("have add rule reply")
|
d.editRulePage.busy = false;
|
||||||
if (ruleError == "RuleErrorNoError") {
|
if (ruleError == "RuleErrorNoError") {
|
||||||
pageStack.pop();
|
pageStack.pop();
|
||||||
|
} else {
|
||||||
|
var errorDialog = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml"));
|
||||||
|
var popup = errorDialog.createObject(root, {errorCode: ruleError })
|
||||||
|
popup.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,7 +95,7 @@ Page {
|
|||||||
height: app.iconSize
|
height: app.iconSize
|
||||||
width: height
|
width: height
|
||||||
name: "../images/magic.svg"
|
name: "../images/magic.svg"
|
||||||
color: !model.enabled ? "gray" : (model.active ? "red" : app.guhAccent)
|
color: !model.enabled ? "red" : (model.active ? app.guhAccent : "grey")
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
@ -82,9 +105,16 @@ Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var editRulePage = pageStack.push(Qt.resolvedUrl("EditRulePage.qml"), {rule: rulesFilterModel.get(index) })
|
d.editRulePage = pageStack.push(Qt.resolvedUrl("EditRulePage.qml"), {rule: rulesFilterModel.get(index).clone() })
|
||||||
editRulePage.onAccept.connect(function() {
|
d.editRulePage.StackView.onRemoved.connect(function() {
|
||||||
Engine.ruleManager.editRule(editRulePage.rule);
|
d.editRulePage.rule.destroy();
|
||||||
|
})
|
||||||
|
d.editRulePage.onAccept.connect(function() {
|
||||||
|
d.editRulePage.busy = true
|
||||||
|
Engine.ruleManager.editRule(d.editRulePage.rule);
|
||||||
|
})
|
||||||
|
d.editRulePage.onCancel.connect(function() {
|
||||||
|
pageStack.pop();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
402
mea/ui/magic/EditCalendarItemPage.qml
Normal file
402
mea/ui/magic/EditCalendarItemPage.qml
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import Qt.labs.calendar 1.0
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import "../components"
|
||||||
|
import Mea 1.0
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var calendarItem: null
|
||||||
|
|
||||||
|
signal done()
|
||||||
|
signal backPressed()
|
||||||
|
|
||||||
|
readonly property bool isDateBased: repeatingBox.currentIndex === 0 ||
|
||||||
|
repeatingBox.currentIndex === 5
|
||||||
|
readonly property bool isWeekDayBased: repeatingBox.currentIndex === 3
|
||||||
|
readonly property bool isMonthDayBased: repeatingBox.currentIndex === 4
|
||||||
|
|
||||||
|
header: GuhHeader {
|
||||||
|
text: qsTr("Pick a time frame")
|
||||||
|
onBackPressed: root.backPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
var date = root.isDateBased ? root.calendarItem.dateTime : root.calendarItem.startTime
|
||||||
|
print("starting with time:", root.calendarItem.startTime, root.calendarItem.dateTime)
|
||||||
|
if (isNaN(date)) {
|
||||||
|
console.log("Date in rule not valid, using current datetime");
|
||||||
|
date = new Date();
|
||||||
|
}
|
||||||
|
hourBox.currentIndex = date.getHours();
|
||||||
|
minuteBox.currentIndex = date.getMinutes();
|
||||||
|
dayBox.currentIndex = date.getDate() - 1;
|
||||||
|
monthBox.currentIndex = date.getMonth();
|
||||||
|
print("should set year to", date.getFullYear())
|
||||||
|
yearBox.currentIndex = date.getFullYear() - 1970;
|
||||||
|
|
||||||
|
var endDate = new Date(date.getTime() + root.calendarItem.duration * 60000);
|
||||||
|
toHourBox.currentIndex = endDate.getHours();
|
||||||
|
toMinuteBox.currentIndex = endDate.getMinutes();
|
||||||
|
toDayBox.currentIndex = endDate.getDate() - 1;
|
||||||
|
toMonthBox.currentIndex = endDate.getMonth();
|
||||||
|
toYearBox.currentIndex = endDate.getFullYear() - 1970
|
||||||
|
}
|
||||||
|
|
||||||
|
function pad(num, size) {
|
||||||
|
var s = "000000000" + num;
|
||||||
|
return s.substr(s.length-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
anchors.fill: parent
|
||||||
|
contentHeight: mainColumn.implicitHeight
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: mainColumn
|
||||||
|
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
columns: app.landscape ? 2 : 1
|
||||||
|
Layout.alignment: app.landscape ? Qt.AlignHCenter : Qt.AlignLeft
|
||||||
|
Layout.margins: app.margins
|
||||||
|
Layout.fillWidth: !app.landscape
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("From")
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
ComboBox {
|
||||||
|
id: hourBox
|
||||||
|
model: {
|
||||||
|
if (!enabled) {
|
||||||
|
return ["--"]
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 0; i < 24; i++) {
|
||||||
|
ret.push(pad(i, 2));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
enabled: repeatingBox.currentIndex !== 1
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: ":"
|
||||||
|
}
|
||||||
|
ComboBox {
|
||||||
|
id: minuteBox
|
||||||
|
model: {
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 0; i < 60; i++) {
|
||||||
|
ret.push(pad(i, 2));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillHeight: !app.landscape
|
||||||
|
Layout.topMargin: app.landscape ? app.margins : 0
|
||||||
|
visible: root.isDateBased
|
||||||
|
ComboBox {
|
||||||
|
id: dayBox
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: {
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 1; i < 31; i++) {
|
||||||
|
ret.push(pad(i, 2));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ComboBox {
|
||||||
|
id: monthBox
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: [
|
||||||
|
qsTr("Jan"),
|
||||||
|
qsTr("Feb"),
|
||||||
|
qsTr("Mar"),
|
||||||
|
qsTr("Apr"),
|
||||||
|
qsTr("May"),
|
||||||
|
qsTr("Jun"),
|
||||||
|
qsTr("Jul"),
|
||||||
|
qsTr("Aug"),
|
||||||
|
qsTr("Sep"),
|
||||||
|
qsTr("Oct"),
|
||||||
|
qsTr("Nov"),
|
||||||
|
qsTr("Dez")
|
||||||
|
]
|
||||||
|
}
|
||||||
|
ComboBox {
|
||||||
|
id: yearBox
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: {
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 1970; i < 2100; i++) {
|
||||||
|
ret.push(i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("To")
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
ComboBox {
|
||||||
|
id: toHourBox
|
||||||
|
model: {
|
||||||
|
if (!enabled) {
|
||||||
|
return ["--"]
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 0; i < 24; i++) {
|
||||||
|
ret.push(pad(i, 2));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
enabled: repeatingBox.currentIndex !== 1
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: ":"
|
||||||
|
}
|
||||||
|
ComboBox {
|
||||||
|
id: toMinuteBox
|
||||||
|
model: {
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 0; i < 60; i++) {
|
||||||
|
ret.push(pad(i, 2));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillHeight: !app.landscape
|
||||||
|
Layout.topMargin: app.landscape ? app.margins : 0
|
||||||
|
visible: root.isDateBased
|
||||||
|
ComboBox {
|
||||||
|
id: toDayBox
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: {
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 1; i < 31; i++) {
|
||||||
|
ret.push(pad(i, 2));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
onActivated: {
|
||||||
|
var date = root.calendarItem.dateTime
|
||||||
|
date.setDate(index)
|
||||||
|
root.calendarItem.dateTime = date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ComboBox {
|
||||||
|
id: toMonthBox
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: [
|
||||||
|
qsTr("Jan"),
|
||||||
|
qsTr("Feb"),
|
||||||
|
qsTr("Mar"),
|
||||||
|
qsTr("Apr"),
|
||||||
|
qsTr("May"),
|
||||||
|
qsTr("Jun"),
|
||||||
|
qsTr("Jul"),
|
||||||
|
qsTr("Aug"),
|
||||||
|
qsTr("Sep"),
|
||||||
|
qsTr("Oct"),
|
||||||
|
qsTr("Nov"),
|
||||||
|
qsTr("Dez")
|
||||||
|
]
|
||||||
|
}
|
||||||
|
ComboBox {
|
||||||
|
id: toYearBox
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: {
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 1970; i < 2100; i++) {
|
||||||
|
ret.push(i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Repeat")
|
||||||
|
Layout.topMargin: app.margins
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: app.landscape ? app.margins : 0
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: repeatingBox
|
||||||
|
model: [qsTr("never"), qsTr("hourly"), qsTr("daily"), qsTr("weekly"), qsTr("monthly"), qsTr("yearly")]
|
||||||
|
|
||||||
|
currentIndex: {
|
||||||
|
switch (root.calendarItem.repeatingOption.repeatingMode) {
|
||||||
|
case RepeatingOption.RepeatingModeNone:
|
||||||
|
return 0;
|
||||||
|
case RepeatingOption.RepeatingModeHourly:
|
||||||
|
return 1;
|
||||||
|
case RepeatingOption.RepeatingModeDaily:
|
||||||
|
return 2;
|
||||||
|
case RepeatingOption.RepeatingModeWeekly:
|
||||||
|
return 3;
|
||||||
|
case RepeatingOption.RepeatingModeMonthly:
|
||||||
|
return 4;
|
||||||
|
case RepeatingOption.RepeatingModeYearly:
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Weekdays")
|
||||||
|
Layout.topMargin: app.margins
|
||||||
|
visible: root.isWeekDayBased
|
||||||
|
}
|
||||||
|
|
||||||
|
DayOfWeekRow {
|
||||||
|
id: weekDayRow
|
||||||
|
property var weekDays: root.calendarItem.repeatingOption.weekDays
|
||||||
|
visible: root.isWeekDayBased
|
||||||
|
Layout.fillWidth: !app.landscape
|
||||||
|
Layout.topMargin: app.landscape ? app.margins : 0
|
||||||
|
delegate: ToolButton {
|
||||||
|
text: model.shortName
|
||||||
|
checked: weekDayRow.weekDays.indexOf(index + 1) >= 0
|
||||||
|
onClicked: {
|
||||||
|
var copy = weekDayRow.weekDays
|
||||||
|
var idx = copy.indexOf(index + 1);
|
||||||
|
if (idx >= 0) {
|
||||||
|
copy.splice(idx, 1);
|
||||||
|
} else {
|
||||||
|
copy.push(index + 1)
|
||||||
|
}
|
||||||
|
weekDayRow.weekDays = copy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Day of month")
|
||||||
|
Layout.topMargin: app.margins
|
||||||
|
visible: root.isMonthDayBased
|
||||||
|
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||||
|
}
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: monthDayGrid
|
||||||
|
columns: Math.sqrt(children.length)
|
||||||
|
Layout.fillWidth: !app.landscape
|
||||||
|
Layout.topMargin: app.landscape ? app.margins : 0
|
||||||
|
visible: root.isMonthDayBased
|
||||||
|
property var monthDays: root.calendarItem.repeatingOption.monthDays
|
||||||
|
Repeater {
|
||||||
|
model: 31
|
||||||
|
delegate: ToolButton {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
checked: monthDayGrid.monthDays.indexOf(index + 1) >= 0
|
||||||
|
text: modelData + 1
|
||||||
|
onClicked: {
|
||||||
|
var copy = monthDayGrid.monthDays
|
||||||
|
var idx = copy.indexOf(index + 1);
|
||||||
|
if (idx >= 0) {
|
||||||
|
copy.splice(idx, 1);
|
||||||
|
} else {
|
||||||
|
copy.push(index + 1)
|
||||||
|
}
|
||||||
|
monthDayGrid.monthDays = copy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: !app.landscape
|
||||||
|
Layout.margins: app.margins
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
text: qsTr("OK")
|
||||||
|
onClicked: {
|
||||||
|
if (root.isDateBased) {
|
||||||
|
var date = isNaN(root.calendarItem.dateTime) ? new Date() : root.calendarItem.dateTime
|
||||||
|
date.setHours(hourBox.currentIndex);
|
||||||
|
date.setMinutes(minuteBox.currentIndex);
|
||||||
|
date.setDate(dayBox.currentIndex + 1);
|
||||||
|
date.setMonth(monthBox.currentIndex);
|
||||||
|
date.setFullYear(yearBox.currentText);
|
||||||
|
root.calendarItem.dateTime = date;
|
||||||
|
|
||||||
|
var endDate = new Date();
|
||||||
|
endDate.setHours(toHourBox.currentIndex);
|
||||||
|
endDate.setMinutes(toMinuteBox.currentIndex);
|
||||||
|
endDate.setDate(toDayBox.currentIndex + 1);
|
||||||
|
endDate.setMilliseconds(toMonthBox.currentIndex);
|
||||||
|
endDate.setFullYear(toYearBox.currentText);
|
||||||
|
root.calendarItem.duration = (endDate.getTime() - date.getTime()) / 60000;
|
||||||
|
} else {
|
||||||
|
var time = isNaN(root.calendarItem.startTime) ? new Date() : root.calendarItem.startTime
|
||||||
|
time.setHours(hourBox.currentIndex);
|
||||||
|
time.setMinutes(minuteBox.currentIndex)
|
||||||
|
root.calendarItem.startTime = time;
|
||||||
|
|
||||||
|
var endTime = new Date(time);
|
||||||
|
endTime.setHours(toHourBox.currentIndex);
|
||||||
|
endTime.setMinutes(toMinuteBox.currentIndex);
|
||||||
|
root.calendarItem.duration = (endTime.getTime() - time.getTime()) / 60000;
|
||||||
|
print("duration is", endTime.getTime() - time.getTime(), time, endTime, toMinuteBox.currentIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (repeatingBox.currentIndex) {
|
||||||
|
case 0:
|
||||||
|
root.calendarItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeNone;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
root.calendarItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeHourly;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
root.calendarItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeDaily;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
root.calendarItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeWeekly;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
root.calendarItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeMonthly;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
root.calendarItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeYearly;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.isWeekDayBased) {
|
||||||
|
root.calendarItem.repeatingOption.weekDays = weekDayRow.weekDays;
|
||||||
|
}
|
||||||
|
if (root.isMonthDayBased) {
|
||||||
|
root.calendarItem.repeatingOption.monthDays = monthDayGrid.monthDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
root.done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,15 +8,17 @@ Page {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var rule: null
|
property var rule: null
|
||||||
|
property bool busy: false
|
||||||
|
|
||||||
signal accept();
|
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
|
||||||
onAccept: busyOverlay.opacity = 1
|
readonly property bool actionsVisible: !isEmpty
|
||||||
|
|
||||||
readonly property bool isStateBased: rule.eventDescriptors.count === 0
|
|
||||||
readonly property bool actionsVisible: rule.eventDescriptors.count > 0 || rule.stateEvaluator !== null
|
|
||||||
readonly property bool exitActionsVisible: actionsVisible && isStateBased
|
readonly property bool exitActionsVisible: actionsVisible && isStateBased
|
||||||
readonly property bool hasExitActions: rule.exitActions.count > 0
|
readonly property bool hasExitActions: rule.exitActions.count > 0
|
||||||
|
readonly property bool isEmpty: !isEventBased && !isStateBased
|
||||||
|
|
||||||
|
signal accept();
|
||||||
|
signal cancel();
|
||||||
|
|
||||||
function addEventDescriptor() {
|
function addEventDescriptor() {
|
||||||
var eventDescriptor = root.rule.eventDescriptors.createNewEventDescriptor();
|
var eventDescriptor = root.rule.eventDescriptors.createNewEventDescriptor();
|
||||||
@ -41,6 +43,32 @@ Page {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addTimeEventItem() {
|
||||||
|
var timeEventItem = root.rule.timeDescriptor.timeEventItems.createNewTimeEventItem();
|
||||||
|
var page = pageStack.push(Qt.resolvedUrl("EditTimeEventItemPage.qml"), {timeEventItem: timeEventItem});
|
||||||
|
page.onBackPressed.connect(function() {
|
||||||
|
pageStack.pop()
|
||||||
|
timeEventItem.destroy();
|
||||||
|
})
|
||||||
|
page.onDone.connect(function() {
|
||||||
|
root.rule.timeDescriptor.timeEventItems.addTimeEventItem(timeEventItem);
|
||||||
|
pageStack.pop();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCalendarItem() {
|
||||||
|
var calendarItem = root.rule.timeDescriptor.calendarItems.createNewCalendarItem();
|
||||||
|
var page = pageStack.push(Qt.resolvedUrl("EditCalendarItemPage.qml"), {calendarItem: calendarItem});
|
||||||
|
page.onBackPressed.connect(function() {
|
||||||
|
pageStack.pop();
|
||||||
|
calendarItem.destroy();
|
||||||
|
})
|
||||||
|
page.onDone.connect(function() {
|
||||||
|
root.rule.timeDescriptor.calendarItems.addCalendarItem(calendarItem);
|
||||||
|
pageStack.pop();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function editStateEvaluator() {
|
function editStateEvaluator() {
|
||||||
print("opening page", root.rule.stateEvaluator)
|
print("opening page", root.rule.stateEvaluator)
|
||||||
var page = pageStack.push(Qt.resolvedUrl("EditStateEvaluatorPage.qml"), { stateEvaluator: root.rule.stateEvaluator })
|
var page = pageStack.push(Qt.resolvedUrl("EditStateEvaluatorPage.qml"), { stateEvaluator: root.rule.stateEvaluator })
|
||||||
@ -91,15 +119,14 @@ Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
header: GuhHeader {
|
header: GuhHeader {
|
||||||
text: qsTr("New rule")
|
text: root.rule.name.length === 0 ? qsTr("Add new magic") : qsTr("Edit %1").arg(root.rule.name)
|
||||||
onBackPressed: pageStack.pop()
|
onBackPressed: root.cancel()
|
||||||
|
|
||||||
HeaderButton {
|
HeaderButton {
|
||||||
imageSource: "../images/tick.svg"
|
imageSource: "../images/tick.svg"
|
||||||
enabled: actionsRepeater.count > 0 && root.rule.name.length > 0
|
enabled: actionsRepeater.count > 0 && root.rule.name.length > 0
|
||||||
opacity: enabled ? 1 : .3
|
opacity: enabled ? 1 : .3
|
||||||
onClicked: {
|
onClicked: root.accept()
|
||||||
root.accept()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,24 +136,47 @@ Page {
|
|||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: contentColumn
|
id: contentColumn
|
||||||
anchors { left: parent.left; top: parent.top; right: parent.right; topMargin: app.margins }
|
anchors { left: parent.left; top: parent.top; right: parent.right; }
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
id: ruleSettings
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: app.margins
|
Layout.leftMargin: app.margins
|
||||||
Label {
|
Layout.rightMargin: app.margins
|
||||||
Layout.fillWidth: true
|
Layout.topMargin: app.margins
|
||||||
text: qsTr("Rule name")
|
|
||||||
}
|
property bool showDetails: false
|
||||||
TextField {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: root.rule.name
|
|
||||||
onTextChanged: {
|
|
||||||
root.rule.name = text;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
spacing: app.margins
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Name:")
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.rule.name
|
||||||
|
onTextChanged: root.rule.name = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorIcon {
|
||||||
|
name: "../images/settings.svg"
|
||||||
|
Layout.preferredHeight: app.iconSize
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: ruleSettings.showDetails = !ruleSettings.showDetails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: ruleSettings.showDetails ? implicitHeight : 0
|
||||||
|
opacity: ruleSettings.showDetails ? 1 : 0
|
||||||
|
Behavior on Layout.preferredHeight { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad} }
|
||||||
|
Behavior on opacity { NumberAnimation {duration: 200; easing.type: Easing.InOutQuad } }
|
||||||
Label {
|
Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("This rule is enabled")
|
text: qsTr("This rule is enabled")
|
||||||
@ -140,83 +190,49 @@ Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThinDivider { visible: !root.hasExitActions }
|
ThinDivider { visible: !root.isStateBased }
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: app.margins
|
Layout.margins: app.margins
|
||||||
font.pixelSize: app.mediumFont
|
font.pixelSize: app.mediumFont
|
||||||
text: qsTr("Events triggering this rule")
|
wrapMode: Text.WordWrap
|
||||||
visible: !root.hasExitActions
|
text: eventsRepeater.count === 0 && timeEventRepeater.count === 0 ?
|
||||||
|
qsTr("Execute actions when something happens.") :
|
||||||
|
qsTr("When any of these events happen...")
|
||||||
|
visible: !root.isStateBased
|
||||||
|
font.bold: true
|
||||||
}
|
}
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: app.margins
|
||||||
|
Layout.rightMargin: app.margins
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
font.pixelSize: app.smallFont
|
||||||
|
font.italic: true
|
||||||
|
text: qsTr("Examples:\n• When a button is pressed...\n• When the temperature changes...\n• At 7 am...")
|
||||||
|
visible: root.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: eventsRepeater
|
id: eventsRepeater
|
||||||
model: root.hasExitActions ? null : root.rule.eventDescriptors
|
model: root.hasExitActions ? null : root.rule.eventDescriptors
|
||||||
delegate: SwipeDelegate {
|
delegate: EventDescriptorDelegate {
|
||||||
id: eventDelegate
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
readonly property var eventDescriptor: root.rule.eventDescriptors.get(index)
|
eventDescriptor: root.rule.eventDescriptors.get(index)
|
||||||
property var device: Engine.deviceManager.devices.getDevice(eventDescriptor.deviceId)
|
onRemoveEventDescriptor: root.rule.eventDescriptors.removeEventDescriptor(index)
|
||||||
property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
}
|
||||||
property var iface: eventDescriptor.interfaceName ? Interfaces.findByName(eventDescriptor.interfaceName) : null
|
}
|
||||||
property var eventType: deviceClass ? deviceClass.eventTypes.getEventType(eventDescriptor.eventTypeId)
|
|
||||||
: iface ? iface.eventTypes.findByName(eventDescriptor.interfaceEvent) : null
|
|
||||||
contentItem: ColumnLayout {
|
|
||||||
Label {
|
|
||||||
text: qsTr("%1 - %2").arg(eventDelegate.device ? eventDelegate.device.name : eventDelegate.iface.displayName).arg(eventDelegate.eventType.displayName)
|
|
||||||
Layout.fillWidth: true
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: app.margins
|
|
||||||
Repeater {
|
|
||||||
model: eventDelegate.eventDescriptor.paramDescriptors
|
|
||||||
Label {
|
|
||||||
text: {
|
|
||||||
var ret = eventDelegate.eventType.paramTypes.getParamType(model.id).displayName
|
|
||||||
switch (model.operator) {
|
|
||||||
case ParamDescriptor.ValueOperatorEquals:
|
|
||||||
ret += " = ";
|
|
||||||
break;
|
|
||||||
case ParamDescriptor.ValueOperatorNotEquals:
|
|
||||||
ret += " != ";
|
|
||||||
break;
|
|
||||||
case ParamDescriptor.ValueOperatorGreater:
|
|
||||||
ret += " > ";
|
|
||||||
break;
|
|
||||||
case ParamDescriptor.ValueOperatorGreaterOrEqual:
|
|
||||||
ret += " >= ";
|
|
||||||
break;
|
|
||||||
case ParamDescriptor.ValueOperatorLess:
|
|
||||||
ret += " < ";
|
|
||||||
break;
|
|
||||||
case ParamDescriptor.ValueOperatorLessOrEqual:
|
|
||||||
ret += " <= ";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ret += " ? ";
|
|
||||||
}
|
|
||||||
|
|
||||||
ret += model.value
|
Repeater {
|
||||||
return ret;
|
id: timeEventRepeater
|
||||||
}
|
model: root.rule.timeDescriptor.timeEventItems
|
||||||
}
|
delegate: TimeEventDelegate {
|
||||||
}
|
Layout.fillWidth: true
|
||||||
}
|
timeEventItem: root.rule.timeDescriptor.timeEventItems.get(index)
|
||||||
}
|
onRemoveTimeEventItem: {
|
||||||
swipe.right: MouseArea {
|
root.rule.timeDescriptor.timeEventItems.removeTimeEventItem(index);
|
||||||
height: eventDelegate.height
|
|
||||||
width: height
|
|
||||||
anchors.right: parent.right
|
|
||||||
ColorIcon {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: app.margins
|
|
||||||
name: "../images/delete.svg"
|
|
||||||
color: "red"
|
|
||||||
}
|
|
||||||
onClicked: root.rule.eventDescriptors.removeEventDescriptor(index)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,18 +240,58 @@ Page {
|
|||||||
Button {
|
Button {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: app.margins
|
Layout.margins: app.margins
|
||||||
text: eventsRepeater.count == 0 ? qsTr("Add an event...") : qsTr("Add another event...")
|
text: eventsRepeater.count == 0 && timeEventRepeater.count === 0 ? qsTr("Configure...") : qsTr("Add another...")
|
||||||
onClicked: root.addEventDescriptor();
|
visible: !root.isStateBased
|
||||||
visible: !root.hasExitActions
|
onClicked: {
|
||||||
|
if (root.rule.timeDescriptor.calendarItems.count > 0) {
|
||||||
|
root.addEventDescriptor()
|
||||||
|
} else {
|
||||||
|
var popup = eventQuestionDialogComponent.createObject(root)
|
||||||
|
popup.open();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThinDivider {}
|
ThinDivider {}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: qsTr("Conditions to be met")
|
text: root.isEmpty ?
|
||||||
|
qsTr("Do something while a condition is met.") :
|
||||||
|
root.isEventBased ?
|
||||||
|
qsTr("...but only if those conditions are met...") :
|
||||||
|
qsTr("When this condition...")
|
||||||
font.pixelSize: app.mediumFont
|
font.pixelSize: app.mediumFont
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: app.margins
|
Layout.margins: app.margins
|
||||||
|
font.bold: true
|
||||||
|
visible: {
|
||||||
|
if (root.isEventBased) {
|
||||||
|
if (root.rule.timeDescriptor.calendarItems.count === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.rule.stateEvaluator === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (root.rule.stateEvaluator === null && root.rule.timeDescriptor.calendarItems.count > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: app.margins
|
||||||
|
Layout.rightMargin: app.margins
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
font.pixelSize: app.smallFont
|
||||||
|
font.italic: true
|
||||||
|
text: qsTr("Examples:\n• While I'm at home...\n• When the temperature is below 0...\n• Between 9 am and 6 pm...")
|
||||||
|
visible: root.isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
StateEvaluatorDelegate {
|
StateEvaluatorDelegate {
|
||||||
@ -244,70 +300,68 @@ Page {
|
|||||||
visible: root.rule.stateEvaluator !== null
|
visible: root.rule.stateEvaluator !== null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: root.rule.stateEvaluator === null && !root.isEventBased ?
|
||||||
|
qsTr("When time is in...") :
|
||||||
|
qsTr("...during this time...")
|
||||||
|
font.pixelSize: app.mediumFont
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: app.margins
|
||||||
|
font.bold: true
|
||||||
|
visible: root.rule.timeDescriptor.timeEventItems.count === 0 && (root.rule.timeDescriptor.calendarItems.count > 0 || root.rule.stateEvaluator !== null)
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: root.rule.timeDescriptor.calendarItems
|
||||||
|
delegate: CalendarItemDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
calendarItem: root.rule.timeDescriptor.calendarItems.get(index)
|
||||||
|
onRemoveCalendarItem: {
|
||||||
|
root.rule.timeDescriptor.calendarItems.removeCalendarItem(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: app.margins
|
Layout.margins: app.margins
|
||||||
text: qsTr("Add a condition")
|
text: root.rule.stateEvaluator === null && root.rule.timeDescriptor.calendarItems.count === 0 ?
|
||||||
visible: root.rule.stateEvaluator === null
|
qsTr("Configure...") :
|
||||||
|
qsTr("Add another...")
|
||||||
|
visible: root.rule.timeDescriptor.timeEventItems.count === 0 || root.rule.stateEvaluator === null
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.rule.createStateEvaluator();
|
if (root.rule.timeDescriptor.timeEventItems.count > 0) {
|
||||||
// root.editStateEvaluator()
|
root.rule.createStateEvaluator()
|
||||||
|
} else if (root.rule.stateEvaluator !== null) {
|
||||||
|
root.addCalendarItem();
|
||||||
|
} else {
|
||||||
|
var popup = stateQuestionDialogComponent.createObject(root)
|
||||||
|
popup.open()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThinDivider { visible: root.actionsVisible }
|
ThinDivider { visible: root.actionsVisible }
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: root.isStateBased ? qsTr("Active state enter actions") : qsTr("Actions to execute")
|
text: root.isStateBased ?
|
||||||
|
(root.rule.stateEvaluator === 0 ? qsTr("...come true, execute those actions:") : qsTr("...comes true, execute those actions:")) :
|
||||||
|
qsTr("...execute those actions:")
|
||||||
font.pixelSize: app.mediumFont
|
font.pixelSize: app.mediumFont
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: app.margins
|
Layout.margins: app.margins
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
visible: root.actionsVisible
|
visible: root.actionsVisible
|
||||||
|
font.bold: true
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: actionsRepeater
|
id: actionsRepeater
|
||||||
model: root.actionsVisible ? root.rule.actions : null
|
model: root.actionsVisible ? root.rule.actions : null
|
||||||
delegate: SwipeDelegate {
|
delegate: RuleActionDelegate {
|
||||||
id: actionDelegate
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
property var ruleAction: root.rule.actions.get(index)
|
ruleAction: root.rule.actions.get(index)
|
||||||
property var device: ruleAction.deviceId ? Engine.deviceManager.devices.getDevice(ruleAction.deviceId) : null
|
onRemoveRuleAction: root.rule.actions.removeRuleAction(index)
|
||||||
property var iface: ruleAction.interfaceName ? Interfaces.findByName(ruleAction.interfaceName) : null
|
|
||||||
property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
|
||||||
property var actionType: deviceClass ? deviceClass.actionTypes.getActionType(ruleAction.actionTypeId)
|
|
||||||
: iface ? iface.actionTypes.findByName(ruleAction.interfaceAction) : null
|
|
||||||
contentItem: ColumnLayout {
|
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: qsTr("%1 - %2").arg(actionDelegate.device ? actionDelegate.device.name : actionDelegate.iface.displayName).arg(actionDelegate.actionType.displayName)
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: app.margins
|
|
||||||
Repeater {
|
|
||||||
model: actionDelegate.ruleAction.ruleActionParams
|
|
||||||
Label {
|
|
||||||
text: actionDelegate.actionType.paramTypes.getParamType(model.paramTypeId).displayName + " -> " +
|
|
||||||
(model.eventParamTypeId.length > 0 ? qsTr("value from event") : model.value)
|
|
||||||
font.pixelSize: app.smallFont
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
swipe.right: MouseArea {
|
|
||||||
height: actionDelegate.height
|
|
||||||
width: height
|
|
||||||
anchors.right: parent.right
|
|
||||||
ColorIcon {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: app.margins
|
|
||||||
name: "../images/delete.svg"
|
|
||||||
color: "red"
|
|
||||||
}
|
|
||||||
onClicked: root.rule.actions.removeRuleAction(index)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,56 +376,23 @@ Page {
|
|||||||
ThinDivider { visible: root.exitActionsVisible }
|
ThinDivider { visible: root.exitActionsVisible }
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: qsTr("Active state exit actions")
|
text: qsTr("...isn't met any more, execute those actions:")
|
||||||
font.pixelSize: app.mediumFont
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: app.margins
|
Layout.margins: app.margins
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
visible: root.exitActionsVisible
|
visible: root.exitActionsVisible
|
||||||
|
font.pixelSize: app.mediumFont
|
||||||
|
font.bold: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: exitActionsRepeater
|
id: exitActionsRepeater
|
||||||
model: root.exitActionsVisible ? root.rule.exitActions : null
|
model: root.exitActionsVisible ? root.rule.exitActions : null
|
||||||
delegate: SwipeDelegate {
|
delegate: RuleActionDelegate {
|
||||||
id: exitActionDelegate
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
property var ruleAction: root.rule.exitActions.get(index)
|
ruleAction: root.rule.exitActions.get(index)
|
||||||
property var device: ruleAction.deviceId ? Engine.deviceManager.devices.getDevice(ruleAction.deviceId) : null
|
onClicked: root.rule.exitActions.removeRuleAction(index)
|
||||||
property var iface: ruleAction.interfaceName ? Interfaces.findByName(ruleAction.interfaceName) : null
|
|
||||||
property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
|
||||||
property var actionType: deviceClass ? deviceClass.actionTypes.getActionType(ruleAction.actionTypeId)
|
|
||||||
: iface ? iface.actionTypes.findByName(ruleAction.interfaceAction) : null
|
|
||||||
contentItem: ColumnLayout {
|
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: qsTr("%1 - %2").arg(exitActionDelegate.device ? exitActionDelegate.device.name : exitActionDelegate.iface.displayName).arg(exitActionDelegate.actionType.displayName)
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: app.margins
|
|
||||||
Repeater {
|
|
||||||
model: exitActionDelegate.ruleAction.ruleActionParams
|
|
||||||
Label {
|
|
||||||
text: exitActionDelegate.actionType.paramTypes.getParamType(model.paramTypeId).displayName + " -> " + model.value
|
|
||||||
font.pixelSize: app.smallFont
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
swipe.right: MouseArea {
|
|
||||||
height: exitActionDelegate.height
|
|
||||||
width: height
|
|
||||||
anchors.right: parent.right
|
|
||||||
ColorIcon {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: app.margins
|
|
||||||
name: "../images/delete.svg"
|
|
||||||
color: "red"
|
|
||||||
}
|
|
||||||
onClicked: root.rule.exitActions.removeRuleAction(index)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,11 +410,145 @@ Page {
|
|||||||
id: busyOverlay
|
id: busyOverlay
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: "#55000000"
|
color: "#55000000"
|
||||||
opacity: 0
|
opacity: root.busy ? 1 : 0
|
||||||
Behavior on opacity { NumberAnimation {duration: 200 } }
|
Behavior on opacity { NumberAnimation {duration: 200 } }
|
||||||
BusyIndicator {
|
BusyIndicator {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
running: parent.opacity > 0
|
running: parent.opacity > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: eventQuestionDialogComponent
|
||||||
|
MeaDialog {
|
||||||
|
id: questionDialog
|
||||||
|
title: qsTr("Add event...")
|
||||||
|
standardButtons: Dialog.Cancel
|
||||||
|
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: (app.largeFont * 2) + (app.margins * 3)
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: app.margins
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
name: "../images/event.svg"
|
||||||
|
color: "black"
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
text: qsTr("When one of my things triggers an event")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
root.addEventDescriptor()
|
||||||
|
questionDialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("or")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: app.margins
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: (app.largeFont * 2) + (app.margins * 3)
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: app.margins
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
name: "../images/alarm-clock.svg"
|
||||||
|
color: "black"
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
text: qsTr("At a particular time or date")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
root.addTimeEventItem()
|
||||||
|
questionDialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: stateQuestionDialogComponent
|
||||||
|
MeaDialog {
|
||||||
|
id: questionDialog
|
||||||
|
title: qsTr("Add condition...")
|
||||||
|
standardButtons: Dialog.Cancel
|
||||||
|
|
||||||
|
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: (app.largeFont * 2) + (app.margins * 3)
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: app.margins
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
name: "../images/state.svg"
|
||||||
|
color: "black"
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
text: qsTr("When one of my things is in a certain state")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
root.rule.createStateEvaluator()
|
||||||
|
questionDialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("or")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: app.margins
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: (app.largeFont * 2) + (app.margins * 3)
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: app.margins
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
name: "../images/clock-app-symbolic.svg"
|
||||||
|
color: "black"
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
text: qsTr("During a given time")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
root.addCalendarItem()
|
||||||
|
questionDialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
301
mea/ui/magic/EditTimeEventItemPage.qml
Normal file
301
mea/ui/magic/EditTimeEventItemPage.qml
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import Qt.labs.calendar 1.0
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import "../components"
|
||||||
|
import Mea 1.0
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var timeEventItem: null
|
||||||
|
|
||||||
|
signal done()
|
||||||
|
signal backPressed()
|
||||||
|
|
||||||
|
readonly property bool isDateBased: repeatingBox.currentIndex === 0 ||
|
||||||
|
repeatingBox.currentIndex === 5
|
||||||
|
readonly property bool isWeekDayBased: repeatingBox.currentIndex === 3
|
||||||
|
readonly property bool isMonthDayBased: repeatingBox.currentIndex === 4
|
||||||
|
|
||||||
|
header: GuhHeader {
|
||||||
|
text: qsTr("Pick a time")
|
||||||
|
onBackPressed: root.backPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
var date = root.isDateBased ? root.timeEventItem.dateTime : root.timeEventItem.time
|
||||||
|
print("starting with time:", root.timeEventItem.time, root.timeEventItem.dateTime)
|
||||||
|
if (isNaN(date)) {
|
||||||
|
console.log("Date in rule not valid, using current datetime");
|
||||||
|
date = new Date();
|
||||||
|
}
|
||||||
|
hourBox.currentIndex = date.getHours();
|
||||||
|
minuteBox.currentIndex = date.getMinutes();
|
||||||
|
dayBox.currentIndex = date.getDate() - 1;
|
||||||
|
monthBox.currentIndex = date.getMonth();
|
||||||
|
print("should set year to", date.getFullYear())
|
||||||
|
yearBox.currentIndex = date.getFullYear() - 1970;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pad(num, size) {
|
||||||
|
var s = "000000000" + num;
|
||||||
|
return s.substr(s.length-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
anchors.fill: parent
|
||||||
|
contentHeight: mainColumn.implicitHeight
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: mainColumn
|
||||||
|
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
columns: app.landscape ? 2 : 1
|
||||||
|
Layout.alignment: app.landscape ? Qt.AlignHCenter : Qt.AlignLeft
|
||||||
|
Layout.margins: app.margins
|
||||||
|
Layout.fillWidth: !app.landscape
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Time")
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
ComboBox {
|
||||||
|
id: hourBox
|
||||||
|
model: {
|
||||||
|
if (!enabled) {
|
||||||
|
return ["--"]
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 0; i < 24; i++) {
|
||||||
|
ret.push(pad(i, 2));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
enabled: repeatingBox.currentIndex !== 1
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: ":"
|
||||||
|
}
|
||||||
|
ComboBox {
|
||||||
|
id: minuteBox
|
||||||
|
model: {
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 0; i < 60; i++) {
|
||||||
|
ret.push(pad(i, 2));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Repeat")
|
||||||
|
Layout.topMargin: app.margins
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: app.landscape ? app.margins : 0
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: repeatingBox
|
||||||
|
model: [qsTr("never"), qsTr("hourly"), qsTr("daily"), qsTr("weekly"), qsTr("monthly"), qsTr("yearly")]
|
||||||
|
|
||||||
|
currentIndex: {
|
||||||
|
switch (root.timeEventItem.repeatingOption.repeatingMode) {
|
||||||
|
case RepeatingOption.RepeatingModeNone:
|
||||||
|
return 0;
|
||||||
|
case RepeatingOption.RepeatingModeHourly:
|
||||||
|
return 1;
|
||||||
|
case RepeatingOption.RepeatingModeDaily:
|
||||||
|
return 2;
|
||||||
|
case RepeatingOption.RepeatingModeWeekly:
|
||||||
|
return 3;
|
||||||
|
case RepeatingOption.RepeatingModeMonthly:
|
||||||
|
return 4;
|
||||||
|
case RepeatingOption.RepeatingModeYearly:
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Date")
|
||||||
|
Layout.topMargin: app.margins
|
||||||
|
visible: root.isDateBased
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillHeight: !app.landscape
|
||||||
|
Layout.topMargin: app.landscape ? app.margins : 0
|
||||||
|
visible: root.isDateBased
|
||||||
|
ComboBox {
|
||||||
|
id: dayBox
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: {
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 1; i < 31; i++) {
|
||||||
|
ret.push(pad(i, 2));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ComboBox {
|
||||||
|
id: monthBox
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: [
|
||||||
|
qsTr("Jan"),
|
||||||
|
qsTr("Feb"),
|
||||||
|
qsTr("Mar"),
|
||||||
|
qsTr("Apr"),
|
||||||
|
qsTr("May"),
|
||||||
|
qsTr("Jun"),
|
||||||
|
qsTr("Jul"),
|
||||||
|
qsTr("Aug"),
|
||||||
|
qsTr("Sep"),
|
||||||
|
qsTr("Oct"),
|
||||||
|
qsTr("Nov"),
|
||||||
|
qsTr("Dez")
|
||||||
|
]
|
||||||
|
}
|
||||||
|
ComboBox {
|
||||||
|
id: yearBox
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: {
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 1970; i < 2100; i++) {
|
||||||
|
ret.push(i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Weekdays")
|
||||||
|
Layout.topMargin: app.margins
|
||||||
|
visible: root.isWeekDayBased
|
||||||
|
}
|
||||||
|
|
||||||
|
DayOfWeekRow {
|
||||||
|
id: weekDayRow
|
||||||
|
property var weekDays: root.timeEventItem.repeatingOption.weekDays
|
||||||
|
visible: root.isWeekDayBased
|
||||||
|
Layout.fillWidth: !app.landscape
|
||||||
|
Layout.topMargin: app.landscape ? app.margins : 0
|
||||||
|
delegate: ToolButton {
|
||||||
|
text: model.shortName
|
||||||
|
checked: weekDayRow.weekDays.indexOf(index + 1) >= 0
|
||||||
|
onClicked: {
|
||||||
|
var copy = weekDayRow.weekDays
|
||||||
|
var idx = copy.indexOf(index + 1);
|
||||||
|
if (idx >= 0) {
|
||||||
|
copy.splice(idx, 1);
|
||||||
|
} else {
|
||||||
|
copy.push(index + 1)
|
||||||
|
}
|
||||||
|
weekDayRow.weekDays = copy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Day of month")
|
||||||
|
Layout.topMargin: app.margins
|
||||||
|
visible: root.isMonthDayBased
|
||||||
|
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||||
|
}
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: monthDayGrid
|
||||||
|
columns: Math.sqrt(children.length)
|
||||||
|
Layout.fillWidth: !app.landscape
|
||||||
|
Layout.topMargin: app.landscape ? app.margins : 0
|
||||||
|
visible: root.isMonthDayBased
|
||||||
|
property var monthDays: root.timeEventItem.repeatingOption.monthDays
|
||||||
|
Repeater {
|
||||||
|
model: 31
|
||||||
|
delegate: ToolButton {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
checked: monthDayGrid.monthDays.indexOf(index + 1) >= 0
|
||||||
|
text: modelData + 1
|
||||||
|
onClicked: {
|
||||||
|
var copy = monthDayGrid.monthDays
|
||||||
|
var idx = copy.indexOf(index + 1);
|
||||||
|
if (idx >= 0) {
|
||||||
|
copy.splice(idx, 1);
|
||||||
|
} else {
|
||||||
|
copy.push(index + 1)
|
||||||
|
}
|
||||||
|
monthDayGrid.monthDays = copy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: !app.landscape
|
||||||
|
Layout.margins: app.margins
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
text: qsTr("OK")
|
||||||
|
onClicked: {
|
||||||
|
if (root.isDateBased) {
|
||||||
|
var date = isNaN(root.timeEventItem.dateTime) ? new Date() : root.timeEventItem.dateTime
|
||||||
|
date.setHours(hourBox.currentIndex);
|
||||||
|
date.setMinutes(minuteBox.currentIndex);
|
||||||
|
date.setDate(dayBox.currentIndex + 1);
|
||||||
|
date.setMonth(monthBox.currentIndex);
|
||||||
|
date.setYear(yearBox.currentText);
|
||||||
|
root.timeEventItem.dateTime = date;
|
||||||
|
} else {
|
||||||
|
var time = isNaN(root.timeEventItem.time) ? new Date() : root.timeEventItem.time
|
||||||
|
time.setHours(hourBox.currentIndex);
|
||||||
|
time.setMinutes(minuteBox.currentIndex)
|
||||||
|
root.timeEventItem.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (repeatingBox.currentIndex) {
|
||||||
|
case 0:
|
||||||
|
root.timeEventItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeNone;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
root.timeEventItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeHourly;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
root.timeEventItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeDaily;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
root.timeEventItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeWeekly;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
root.timeEventItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeMonthly;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
root.timeEventItem.repeatingOption.repeatingMode = RepeatingOption.RepeatingModeYearly;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.isWeekDayBased) {
|
||||||
|
root.timeEventItem.repeatingOption.weekDays = weekDayRow.weekDays;
|
||||||
|
}
|
||||||
|
if (root.isMonthDayBased) {
|
||||||
|
root.timeEventItem.repeatingOption.monthDays = monthDayGrid.monthDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
root.done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
99
mea/ui/magic/EventDescriptorDelegate.qml
Normal file
99
mea/ui/magic/EventDescriptorDelegate.qml
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import Mea 1.0
|
||||||
|
import "../components"
|
||||||
|
|
||||||
|
SwipeDelegate {
|
||||||
|
id: root
|
||||||
|
implicitHeight: app.delegateHeight
|
||||||
|
|
||||||
|
property var eventDescriptor: null
|
||||||
|
readonly property var device: eventDescriptor ? Engine.deviceManager.devices.getDevice(eventDescriptor.deviceId) : null
|
||||||
|
readonly property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
||||||
|
readonly property var iface: eventDescriptor.interfaceName ? Interfaces.findByName(eventDescriptor.interfaceName) : null
|
||||||
|
readonly property var eventType: deviceClass ? deviceClass.eventTypes.getEventType(eventDescriptor.eventTypeId)
|
||||||
|
: iface ? iface.eventTypes.findByName(eventDescriptor.interfaceEvent) : null
|
||||||
|
|
||||||
|
signal removeEventDescriptor()
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: app.margins
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
name: "../images/event.svg"
|
||||||
|
color: app.guhAccent
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Label {
|
||||||
|
text: qsTr("%1 - %2").arg(root.device ? root.device.name : root.iface.displayName).arg(root.eventType.displayName)
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pixelSize: app.smallFont
|
||||||
|
text: {
|
||||||
|
var ret = qsTr("anytime");
|
||||||
|
for (var i = 0; i < root.eventDescriptor.paramDescriptors.count; i++) {
|
||||||
|
var paramDescriptor = root.eventDescriptor.paramDescriptors.get(i)
|
||||||
|
var operatorString;
|
||||||
|
switch (paramDescriptor.operatorType) {
|
||||||
|
case ParamDescriptor.ValueOperatorEquals:
|
||||||
|
operatorString = " = ";
|
||||||
|
break;
|
||||||
|
case ParamDescriptor.ValueOperatorNotEquals:
|
||||||
|
operatorString = " != ";
|
||||||
|
break;
|
||||||
|
case ParamDescriptor.ValueOperatorGreater:
|
||||||
|
operatorString = " > ";
|
||||||
|
break;
|
||||||
|
case ParamDescriptor.ValueOperatorGreaterOrEqual:
|
||||||
|
operatorString = " >= ";
|
||||||
|
break;
|
||||||
|
case ParamDescriptor.ValueOperatorLess:
|
||||||
|
operatorString = " < ";
|
||||||
|
break;
|
||||||
|
case ParamDescriptor.ValueOperatorLessOrEqual:
|
||||||
|
operatorString = " <= ";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
operatorString = " ? ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i === 0) {
|
||||||
|
// TRANSLATORS: example: "only if temperature > 5"
|
||||||
|
ret = qsTr("only if %1 %2 %3")
|
||||||
|
.arg(root.eventType.paramTypes.getParamType(paramDescriptor.paramTypeId).displayName)
|
||||||
|
.arg(operatorString)
|
||||||
|
.arg(paramDescriptor.value)
|
||||||
|
} else {
|
||||||
|
// TRANSLATORS: example: "and temperature > 5"
|
||||||
|
ret += " " + qsTr("and %1 %2 %3")
|
||||||
|
.arg(root.eventType.paramTypes.getParamType(paramDescriptor.paramTypeId).displayName)
|
||||||
|
.arg(operatorString)
|
||||||
|
.arg(model.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
swipe.right: MouseArea {
|
||||||
|
height: root.height
|
||||||
|
width: height
|
||||||
|
anchors.right: parent.right
|
||||||
|
ColorIcon {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: app.margins
|
||||||
|
name: "../images/delete.svg"
|
||||||
|
color: "red"
|
||||||
|
}
|
||||||
|
onClicked: root.removeEventDescriptor()
|
||||||
|
}
|
||||||
|
}
|
||||||
66
mea/ui/magic/RuleActionDelegate.qml
Normal file
66
mea/ui/magic/RuleActionDelegate.qml
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import Mea 1.0
|
||||||
|
import "../components"
|
||||||
|
|
||||||
|
SwipeDelegate {
|
||||||
|
id: root
|
||||||
|
implicitHeight: app.delegateHeight
|
||||||
|
property var ruleAction: null
|
||||||
|
|
||||||
|
property var device: ruleAction.deviceId ? Engine.deviceManager.devices.getDevice(ruleAction.deviceId) : null
|
||||||
|
property var iface: ruleAction.interfaceName ? Interfaces.findByName(ruleAction.interfaceName) : null
|
||||||
|
property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
||||||
|
property var actionType: deviceClass ? deviceClass.actionTypes.getActionType(ruleAction.actionTypeId)
|
||||||
|
: iface ? iface.actionTypes.findByName(ruleAction.interfaceAction) : null
|
||||||
|
|
||||||
|
signal removeRuleAction()
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: app.margins
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
name: "../images/action.svg"
|
||||||
|
color: app.guhAccent
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: qsTr("%1 - %2").arg(root.device ? root.device.name : root.iface.displayName).arg(root.actionType.displayName)
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pixelSize: app.smallFont
|
||||||
|
text: {
|
||||||
|
var ret = [];
|
||||||
|
for (var i = 0; i < root.ruleAction.ruleActionParams.count; i++) {
|
||||||
|
var ruleActionParam = root.ruleAction.ruleActionParams.get(i)
|
||||||
|
var paramString = qsTr("%1: %2")
|
||||||
|
.arg(root.actionType.paramTypes.getParamType(ruleActionParam.paramTypeId).displayName)
|
||||||
|
.arg(ruleActionParam.eventParamTypeId.length > 0 ? qsTr("value from event") : ruleActionParam.value)
|
||||||
|
ret.push(paramString)
|
||||||
|
}
|
||||||
|
return ret.join(', ')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
swipe.right: MouseArea {
|
||||||
|
height: root.height
|
||||||
|
width: height
|
||||||
|
anchors.right: parent.right
|
||||||
|
ColorIcon {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: app.margins
|
||||||
|
name: "../images/delete.svg"
|
||||||
|
color: "red"
|
||||||
|
}
|
||||||
|
onClicked: root.removeRuleAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -96,6 +96,7 @@ Page {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: app.margins
|
anchors.margins: app.margins
|
||||||
text: eventDescriptorParamsFilterModel.device.name + " - " + eventDescriptorParamsFilterModel.eventType.displayName + " - " + eventDescriptorParamsFilterModel.paramDescriptor.displayName
|
text: eventDescriptorParamsFilterModel.device.name + " - " + eventDescriptorParamsFilterModel.eventType.displayName + " - " + eventDescriptorParamsFilterModel.paramDescriptor.displayName
|
||||||
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
109
mea/ui/magic/TimeEventDelegate.qml
Normal file
109
mea/ui/magic/TimeEventDelegate.qml
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import Mea 1.0
|
||||||
|
import "../components"
|
||||||
|
|
||||||
|
SwipeDelegate {
|
||||||
|
id: root
|
||||||
|
implicitHeight: app.delegateHeight
|
||||||
|
|
||||||
|
property var timeEventItem: null
|
||||||
|
|
||||||
|
readonly property bool isDateBased: timeEventItem.repeatingOption.repeatingMode === RepeatingOption.RepeatingModeNone ||
|
||||||
|
timeEventItem.repeatingOption.repeatingMode === RepeatingOption.RepeatingModeYearly
|
||||||
|
|
||||||
|
signal removeTimeEventItem();
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: app.margins
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
name: "../images/alarm-clock.svg"
|
||||||
|
color: app.guhAccent
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: qsTr("At %1").arg(root.isDateBased ? Qt.formatDateTime(root.timeEventItem.dateTime) : Qt.formatTime(root.timeEventItem.time))
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("repeated %1").arg(repeatingString)
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pixelSize: app.smallFont
|
||||||
|
|
||||||
|
property string repeatingString: {
|
||||||
|
switch (root.timeEventItem.repeatingOption.repeatingMode) {
|
||||||
|
case RepeatingOption.RepeatingModeNone:
|
||||||
|
return qsTr("never");
|
||||||
|
case RepeatingOption.RepeatingModeHourly:
|
||||||
|
return qsTr("hourly");
|
||||||
|
case RepeatingOption.RepeatingModeDaily:
|
||||||
|
return qsTr("daily");
|
||||||
|
case RepeatingOption.RepeatingModeWeekly:
|
||||||
|
var weekdays = []
|
||||||
|
for (var i = 0; i < root.timeEventItem.repeatingOption.weekDays.length; i++) {
|
||||||
|
switch (root.timeEventItem.repeatingOption.weekDays[i]) {
|
||||||
|
case 1:
|
||||||
|
weekdays.push(qsTr("Mon"));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
weekdays.push(qsTr("Tue"));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
weekdays.push(qsTr("Wed"));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
weekdays.push(qsTr("Thu"));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
weekdays.push(qsTr("Fri"));
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
weekdays.push(qsTr("Sat"));
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
weekdays.push(qsTr("Sun"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qsTr("weekly on %1").arg(weekdays.join(', '));
|
||||||
|
case RepeatingOption.RepeatingModeMonthly:
|
||||||
|
return qsTr("monthly on the %1").arg(root.timeEventItem.repeatingOption.monthDays.join(', '));
|
||||||
|
case RepeatingOption.RepeatingModeYearly:
|
||||||
|
return qsTr("every year");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swipe.right: MouseArea {
|
||||||
|
height: root.height
|
||||||
|
width: height
|
||||||
|
anchors.right: parent.right
|
||||||
|
ColorIcon {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: app.margins
|
||||||
|
name: "../images/delete.svg"
|
||||||
|
color: "red"
|
||||||
|
}
|
||||||
|
onClicked: root.removeTimeEventItem()
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
var page = pageStack.push(Qt.resolvedUrl("EditTimeEventItemPage.qml"), {timeEventItem: root.timeEventItem})
|
||||||
|
page.onBackPressed.connect(function() {pageStack.pop()})
|
||||||
|
page.onDone.connect(function() {
|
||||||
|
pageStack.pop()
|
||||||
|
print("timeeventItem.time is now", root.timeEventItem.time)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -30,7 +30,7 @@ Page {
|
|||||||
pageStack.pop();
|
pageStack.pop();
|
||||||
} else {
|
} else {
|
||||||
console.warn("Error saving plugin params:", JSON.stringify(params))
|
console.warn("Error saving plugin params:", JSON.stringify(params))
|
||||||
var dialog = errorDialog.createObject(root, {title: "Error", text: qsTr("Error saving params: ") + JSON.stringify(params.params.deviceError)});
|
var dialog = errorDialog.createObject(root, {errorCode: params.params.deviceError});
|
||||||
dialog.open();
|
dialog.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user