more work

pull/1/head
Michael Zanetti 2018-02-25 05:48:36 +01:00
parent 294cff0fb3
commit 93c91d71bd
44 changed files with 835 additions and 330 deletions

View File

@ -0,0 +1,57 @@
#include "basicconfiguration.h"
#include "jsonrpc/jsonrpcclient.h"
BasicConfiguration::BasicConfiguration(JsonRpcClient* client, QObject *parent) :
QObject(parent),
m_client(client)
{
}
bool BasicConfiguration::debugServerEnabled() const
{
return m_debugServerEnabled;
}
void BasicConfiguration::setDebugServerEnabled(bool debugServerEnabled)
{
QVariantMap params;
params.insert("enabled", debugServerEnabled);
m_client->sendCommand("Configuration.SetDebugServerEnabled", params, this, "setDebugServerEnabledResponse");
}
QString BasicConfiguration::serverName() const
{
return m_serverName;
}
void BasicConfiguration::setServerName(const QString &serverName)
{
QVariantMap params;
params.insert("serverName", serverName);
m_client->sendCommand("Configuration.SetServerName", params, this, "setServerNameResponse");
}
void BasicConfiguration::init()
{
m_client->sendCommand("Configuration.GetConfigurations", this, "getConfigurationsResponse");
}
void BasicConfiguration::getConfigurationsResponse(const QVariantMap &params)
{
qDebug() << "have config reply" << params;
QVariantMap basicConfig = params.value("params").toMap().value("basicConfiguration").toMap();
m_debugServerEnabled = basicConfig.value("debugServerEnabled").toBool();
m_serverName = basicConfig.value("serverName").toString();
}
void BasicConfiguration::setDebugServerEnabledResponse(const QVariantMap &params)
{
qDebug() << "Debug server set:" << params;
}
void BasicConfiguration::setServerNameResponse(const QVariantMap &params)
{
qDebug() << "Server name set:" << params;
}

View File

@ -0,0 +1,39 @@
#ifndef BASICCONFIGURATION_H
#define BASICCONFIGURATION_H
#include <QObject>
class JsonRpcClient;
class BasicConfiguration : public QObject
{
Q_OBJECT
Q_PROPERTY(bool debugServerEnabled READ debugServerEnabled WRITE setDebugServerEnabled NOTIFY debugServerEnabledChanged)
Q_PROPERTY(QString serverName READ serverName WRITE setServerName NOTIFY serverNameChanged)
public:
explicit BasicConfiguration(JsonRpcClient* client, QObject *parent = nullptr);
bool debugServerEnabled() const;
void setDebugServerEnabled(bool debugServerEnabled);
QString serverName() const;
void setServerName(const QString &serverName);
void init();
private:
Q_INVOKABLE void getConfigurationsResponse(const QVariantMap &params);
Q_INVOKABLE void setDebugServerEnabledResponse(const QVariantMap &params);
Q_INVOKABLE void setServerNameResponse(const QVariantMap &params);
signals:
void debugServerEnabledChanged();
void serverNameChanged();
private:
JsonRpcClient* m_client = nullptr;
bool m_debugServerEnabled = false;
QString m_serverName;
};
#endif // BASICCONFIGURATION_H

View File

@ -151,6 +151,35 @@ void DeviceManager::getPluginsResponse(const QVariantMap &params)
}
}
m_jsonClient->sendCommand("Devices.GetSupportedVendors", this, "getVendorsResponse");
if (m_plugins->count() > 0) {
m_currentGetConfigIndex = 0;
QVariantMap configRequestParams;
configRequestParams.insert("pluginId", m_plugins->get(m_currentGetConfigIndex)->pluginId());
m_jsonClient->sendCommand("Devices.GetPluginConfiguration", configRequestParams, this, "getPluginConfigResponse");
}
}
void DeviceManager::getPluginConfigResponse(const QVariantMap &params)
{
qDebug() << "plugin config response" << params;
Plugin *p = m_plugins->get(m_currentGetConfigIndex);
if (!p) {
qDebug() << "Received a plugin config for a plugin we don't know";
return;
}
QVariantList pluginParams = params.value("params").toMap().value("configuration").toList();
foreach (const QVariant &paramVariant, pluginParams) {
Param* param = JsonTypes::unpackParam(paramVariant.toMap(), p->params());
p->params()->addParam(param);
}
m_currentGetConfigIndex++;
if (m_plugins->count() > m_currentGetConfigIndex) {
QVariantMap configRequestParams;
configRequestParams.insert("pluginId", m_plugins->get(m_currentGetConfigIndex)->pluginId());
m_jsonClient->sendCommand("Devices.GetPluginConfiguration", configRequestParams, this, "getPluginConfigResponse");
}
}
void DeviceManager::getConfiguredDevicesResponse(const QVariantMap &params)
@ -221,6 +250,29 @@ void DeviceManager::confirmPairingResponse(const QVariantMap &params)
emit confirmPairingReply(params.value("params").toMap());
}
void DeviceManager::setPluginConfigResponse(const QVariantMap &params)
{
qDebug() << "set plugin config respionse" << params;
emit savePluginConfigReply(params);
}
void DeviceManager::savePluginConfig(const QUuid &pluginId)
{
Plugin *p = m_plugins->getPlugin(pluginId);
if (!p) {
qWarning()<< "Error: can't find plugin with id" << pluginId;
return;
}
QVariantMap params;
params.insert("pluginId", pluginId);
QVariantList pluginParams;
for (int i = 0; i < p->params()->rowCount(); i++) {
pluginParams.append(JsonTypes::packParam(p->params()->get(i)));
}
params.insert("configuration", pluginParams);
m_jsonClient->sendCommand("Devices.SetPluginConfiguration", params, this, "setPluginConfigResponse");
}
void DeviceManager::addDiscoveredDevice(const QUuid &deviceClassId, const QUuid &deviceDescriptorId, const QString &name)
{
qDebug() << "JsonRpc: add discovered device " << deviceClassId.toString();

View File

@ -63,17 +63,23 @@ private:
Q_INVOKABLE void getVendorsResponse(const QVariantMap &params);
Q_INVOKABLE void getSupportedDevicesResponse(const QVariantMap &params);
Q_INVOKABLE void getPluginsResponse(const QVariantMap &params);
Q_INVOKABLE void getPluginConfigResponse(const QVariantMap &params);
Q_INVOKABLE void getConfiguredDevicesResponse(const QVariantMap &params);
Q_INVOKABLE void addDeviceResponse(const QVariantMap &params);
Q_INVOKABLE void removeDeviceResponse(const QVariantMap &params);
Q_INVOKABLE void pairDeviceResponse(const QVariantMap &params);
Q_INVOKABLE void confirmPairingResponse(const QVariantMap &params);
Q_INVOKABLE void setPluginConfigResponse(const QVariantMap &params);
public slots:
void savePluginConfig(const QUuid &pluginId);
signals:
void pairDeviceReply(const QVariantMap &params);
void confirmPairingReply(const QVariantMap &params);
void addDeviceReply(const QVariantMap &params);
void removeDeviceReply(const QVariantMap &params);
void savePluginConfigReply(const QVariantMap &params);
private:
Vendors *m_vendors;
@ -81,6 +87,8 @@ private:
Devices *m_devices;
DeviceClasses *m_deviceClasses;
int m_currentGetConfigIndex = 0;
JsonRpcClient *m_jsonClient = nullptr;
};

View File

@ -23,6 +23,7 @@
#include "tcpsocketinterface.h"
#include "rulemanager.h"
#include "logmanager.h"
#include "basicconfiguration.h"
Engine* Engine::s_instance = 0;
@ -62,6 +63,11 @@ LogManager *Engine::logManager() const
return m_logManager;
}
BasicConfiguration *Engine::basicConfiguration() const
{
return m_basicConfiguration;
}
GuhConnection *Engine::connection() const
{
return m_connection;
@ -73,7 +79,8 @@ Engine::Engine(QObject *parent) :
m_jsonRpcClient(new JsonRpcClient(m_connection, this)),
m_deviceManager(new DeviceManager(m_jsonRpcClient, this)),
m_ruleManager(new RuleManager(m_jsonRpcClient, this)),
m_logManager(new LogManager(m_jsonRpcClient, this))
m_logManager(new LogManager(m_jsonRpcClient, this)),
m_basicConfiguration(new BasicConfiguration(m_jsonRpcClient, this))
{
connect(m_jsonRpcClient, &JsonRpcClient::connectedChanged, this, &Engine::onConnectedChanged);
connect(m_jsonRpcClient, &JsonRpcClient::authenticationRequiredChanged, this, &Engine::onConnectedChanged);
@ -88,6 +95,7 @@ void Engine::onConnectedChanged()
if (!m_jsonRpcClient->initialSetupRequired() && !m_jsonRpcClient->authenticationRequired()) {
m_deviceManager->init();
m_ruleManager->init();
m_basicConfiguration->init();
}
}
}

View File

@ -31,6 +31,7 @@
class RuleManager;
class LogManager;
class BasicConfiguration;
class Engine : public QObject
{
@ -39,6 +40,7 @@ class Engine : public QObject
Q_PROPERTY(DeviceManager* deviceManager READ deviceManager CONSTANT)
Q_PROPERTY(RuleManager* ruleManager READ ruleManager CONSTANT)
Q_PROPERTY(JsonRpcClient* jsonRpcClient READ jsonRpcClient CONSTANT)
Q_PROPERTY(BasicConfiguration* basicConfiguration READ basicConfiguration CONSTANT)
public:
static Engine *instance();
@ -52,6 +54,7 @@ public:
RuleManager *ruleManager() const;
JsonRpcClient *jsonRpcClient() const;
LogManager *logManager() const;
BasicConfiguration* basicConfiguration() const;
private:
explicit Engine(QObject *parent = 0);
@ -62,6 +65,7 @@ private:
DeviceManager *m_deviceManager;
RuleManager *m_ruleManager;
LogManager *m_logManager;
BasicConfiguration *m_basicConfiguration;
private slots:
void onConnectedChanged();

View File

@ -36,7 +36,8 @@ HEADERS += engine.h \
models/logsmodel.h \
models/valuelogsproxymodel.h \
discovery/guhdiscovery.h \
logmanager.h
logmanager.h \
basicconfiguration.h
SOURCES += main.cpp \
@ -68,7 +69,8 @@ SOURCES += main.cpp \
models/logsmodel.cpp \
models/valuelogsproxymodel.cpp \
discovery/guhdiscovery.cpp \
logmanager.cpp
logmanager.cpp \
basicconfiguration.cpp
withavahi {
DEFINES += WITH_AVAHI

View File

@ -254,7 +254,7 @@ QVariantMap JsonTypes::packRule(Rule *rule)
QVariantList paramDescriptors;
for (int j = 0; j < rule->eventDescriptors()->get(i)->paramDescriptors()->rowCount(); j++) {
QVariantMap paramDescriptor;
paramDescriptor.insert("paramTypeId", rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->id());
paramDescriptor.insert("paramTypeId", rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->paramTypeId());
paramDescriptor.insert("value", rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->value());
QMetaEnum operatorEnum = QMetaEnum::fromType<ParamDescriptor::ValueOperator>();
paramDescriptor.insert("operator", operatorEnum.valueToKey(rule->eventDescriptors()->get(i)->paramDescriptors()->get(j)->operatorType()));
@ -270,6 +270,14 @@ QVariantMap JsonTypes::packRule(Rule *rule)
return ret;
}
QVariantMap JsonTypes::packParam(Param *param)
{
QVariantMap ret;
ret.insert("paramTypeId", param->paramTypeId());
ret.insert("value", param->value());
return ret;
}
DeviceClass::SetupMethod JsonTypes::stringToSetupMethod(const QString &setupMethodString)
{
if (setupMethodString == "SetupMethodJustAdd") {

View File

@ -56,6 +56,7 @@ public:
static Device *unpackDevice(const QVariantMap &deviceMap, QObject *parent);
static QVariantMap packRule(Rule* rule);
static QVariantMap packParam(Param *param);
private:
static DeviceClass::SetupMethod stringToSetupMethod(const QString &setupMethodString);
static QList<DeviceClass::BasicTag> stringListToBasicTags(const QStringList &basicTagsStringList);

View File

@ -44,6 +44,7 @@
#include "types/rule.h"
#include "models/logsmodel.h"
#include "models/valuelogsproxymodel.h"
#include "basicconfiguration.h"
int main(int argc, char *argv[])
{
@ -105,6 +106,7 @@ int main(int argc, char *argv[])
qmlRegisterUncreatableType<EventDescriptor>(uri, 1, 0, "EventDescriptor", "Get them from rules");
qmlRegisterUncreatableType<ParamTypes>(uri, 1, 0, "ParamTypes", "Uncreatable");
qmlRegisterUncreatableType<ParamType>(uri, 1, 0, "ParamType", "Uncreatable");
qmlRegisterType<Param>(uri, 1, 0, "Param");
qmlRegisterUncreatableType<ParamDescriptor>(uri, 1, 0, "ParamDescriptor", "Uncreatable");
qmlRegisterUncreatableType<ParamDescriptors>(uri, 1, 0, "ParamDescriptors", "Uncreatable");
@ -112,6 +114,8 @@ int main(int argc, char *argv[])
qmlRegisterUncreatableType<Plugins>(uri, 1, 0, "Plugins", "Can't create this in QML. Get it from the DeviceManager.");
qmlRegisterType<PluginsProxy>(uri, 1, 0, "PluginsProxy");
qmlRegisterUncreatableType<BasicConfiguration>(uri, 1, 0, "BasicConfiguration", "Uncreatable");
qmlRegisterType<GuhDiscovery>(uri, 1, 0, "GuhDiscovery");
qmlRegisterUncreatableType<DiscoveryModel>(uri, 1, 0, "DiscoveryModel", "Get it from GuhDiscovery");

View File

@ -15,6 +15,7 @@ bool LogsModel::busy() const
int LogsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_list.count();
}
@ -174,7 +175,6 @@ void LogsModel::logsReply(const QVariantMap &data)
LogEntry::LoggingEventType loggingEventType = (LogEntry::LoggingEventType)loggingEventTypeEnum.keyToValue(entryMap.value("eventType").toByteArray());
LogEntry *entry = new LogEntry(timeStamp, value, deviceId, typeId, loggingSource, loggingEventType, this);
m_list.append(entry);
qDebug() << "Added log entry" << entry->dayString() << entry->value() << entry->deviceId() << entryMap << loggingEventType;
}
endResetModel();
@ -199,7 +199,6 @@ void LogsModel::newLogEntryReceived(const QVariantMap &data)
LogEntry::LoggingEventType loggingEventType = (LogEntry::LoggingEventType)loggingEventTypeEnum.keyToValue(entryMap.value("eventType").toByteArray());
LogEntry *entry = new LogEntry(timeStamp, value, deviceId, typeId, loggingSource, loggingEventType, this);
m_list.append(entry);
qDebug() << "Added log entry" << entry->dayString() << entry->value() << entry->deviceId() << entryMap << loggingEventType;
endInsertRows();
emit countChanged();
}

View File

@ -34,7 +34,6 @@
<file>ui/images/torch-on.svg</file>
<file>ui/images/media-preview-start.svg</file>
<file>ui/MagicPage.qml</file>
<file>ui/magic/NewRulePage.qml</file>
<file>ui/images/mediaplayer-app-symbolic.svg</file>
<file>ui/images/system-shutdown.svg</file>
<file>ui/devicepages/ButtonDevicePage.qml</file>
@ -121,5 +120,9 @@
<file>ui/system/LogViewerPage.qml</file>
<file>ui/images/next.svg</file>
<file>ui/images/go-down.svg</file>
<file>ui/system/PluginsPage.qml</file>
<file>ui/system/PluginParamsPage.qml</file>
<file>ui/paramdelegates-ng/ParamDelegate.qml</file>
<file>ui/components/ErrorDialog.qml</file>
</qresource>
</RCC>

View File

@ -74,7 +74,7 @@ void RuleManager::editRule(Rule *rule)
void RuleManager::handleRulesNotification(const QVariantMap &params)
{
qDebug() << "rules notification received" << params;
// qDebug() << "rules notification received" << params;
if (params.value("notification").toString() == "Rules.RuleAdded") {
QVariantMap ruleMap = params.value("params").toMap().value("rule").toMap();
QUuid ruleId = ruleMap.value("id").toUuid();
@ -94,6 +94,8 @@ void RuleManager::handleRulesNotification(const QVariantMap &params)
} else if (params.value("notification").toString() == "Rules.RuleRemoved") {
QUuid ruleId = params.value("params").toMap().value("ruleId").toUuid();
m_rules->remove(ruleId);
} else {
qWarning() << "Unhandled rule notification" << params;
}
}
@ -146,7 +148,7 @@ void RuleManager::removeRuleReply(const QVariantMap &params)
void RuleManager::onEditRuleReply(const QVariantMap &params)
{
qDebug() << "Edit rule reply:" << params.value("params").toMap();
qDebug() << "Edit rule reply:" << params.value("params").toMap().value("ruleError").toString();
emit editRuleReply(params.value("params").toMap().value("ruleError").toString());
}

View File

@ -37,7 +37,7 @@ Page {
MenuSeparator {}
IconMenuItem {
iconSource: "../images/settings.svg"
text: "App settings"
text: "Settings"
onTriggered: pageStack.push(Qt.resolvedUrl("SettingsPage.qml"))
}
MenuSeparator {}
@ -50,13 +50,13 @@ Page {
ColumnLayout {
anchors.fill: parent
anchors.margins: app.margins
SwipeView {
id: swipeView
Layout.fillWidth: true
Layout.fillHeight: true
currentIndex: pageIndicator.currentIndex
clip: true
DevicesPage {
width: parent.view.width

View File

@ -14,13 +14,18 @@ Page {
}
ColumnLayout {
anchors { left: parent.left; right: parent.right; top: parent.top; margins: app.margins }
anchors { left: parent.left; right: parent.right; top: parent.top }
ColumnLayout {
Layout.fillWidth: true
Layout.margins: app.margins
Label {
Layout.fillWidth: true
text: "Application".toUpperCase()
color: app.guhAccent
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
Label {
@ -84,4 +89,66 @@ Page {
}
}
ThinDivider {}
Label {
Layout.fillWidth: true
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
Layout.topMargin: app.margins
text: "System".toUpperCase()
color: app.guhAccent
}
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
spacing: app.margins
Label {
text: qsTr("Debug server enabled")
Layout.fillWidth: true
}
Switch {
checked: Engine.basicConfiguration.debugServerEnabled
onClicked: Engine.basicConfiguration.debugServerEnabled = checked
}
}
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
spacing: app.margins
Label {
text: qsTr("Server name")
}
TextField {
Layout.fillWidth: true
text: Engine.basicConfiguration.serverName
onAccepted: Engine.basicConfiguration.serverName = text
}
}
ItemDelegate {
Layout.fillWidth: true
contentItem: RowLayout {
Label {
Layout.fillWidth: true
text: "Plugins"
}
Image {
source: "images/next.svg"
Layout.preferredHeight: parent.height
Layout.preferredWidth: height
}
}
onClicked: {
pageStack.push(Qt.resolvedUrl("system/PluginsPage.qml"))
}
}
}
}

View File

@ -14,7 +14,7 @@ ActionDelegateBase {
Label {
Layout.fillWidth: true
verticalAlignment: Text.AlignVCenter
text: root.actionType ? root.actionType.name : ""
text: root.actionType ? root.actionType.displayName : ""
}
Switch {
position: root.actionState ? root.actionState : 0

View File

@ -12,7 +12,7 @@ ActionDelegateBase {
Label {
Layout.fillWidth: true
text: root.actionType.paramTypes.get(0).name
text: root.actionType.paramTypes.get(0).displayName
}
Slider {

View File

@ -11,7 +11,7 @@ ActionDelegateBase {
id: layout
anchors { left: parent.left; top: parent.top; right: parent.right; margins: app.margins }
Label {
text: root.paramType.name
text: root.paramType.displayName
Layout.fillWidth: true
}
ComboBox {

View File

@ -0,0 +1,20 @@
import QtQuick 2.8
import QtQuick.Controls 2.1
Dialog {
width: parent.width * .6
height: parent.height * .6
x: (parent.width - width) / 2
y: (parent.height - height) / 2
title: qsTr("Error")
property alias text: contentLabel.text
standardButtons: Dialog.Ok
Label {
id: contentLabel
width: parent.width
wrapMode: Text.WordWrap
}
}

View File

@ -39,8 +39,8 @@ Page {
page = "ButtonDevicePage.qml";
} else if (deviceClass.interfaces.indexOf("weather") >= 0) {
page = "WeatherDevicePage.qml";
// } else if (deviceClass.interfaces.indexOf("sensor") >= 0) {
// page = "SensorDevicePage.qml";
} else if (deviceClass.interfaces.indexOf("sensor") >= 0) {
page = "SensorDevicePage.qml";
} else {
page = "GenericDevicePage.qml";
}

View File

@ -3,6 +3,7 @@ import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import Guh 1.0
import "../components"
import "../paramdelegates-ng"
Page {
id: root
@ -29,25 +30,24 @@ Page {
pageStack.pop();
return;
}
print("Remove device error!", params)
var popup = errorDialog.createObject(root, {text: "Remove device error: " + JSON.stringify(params.deviceError) })
popup.open();
}
}
ListView {
anchors.fill: parent
model: root.device.params
delegate: ItemDelegate {
delegate: ParamDelegate {
width: parent.width
contentItem: RowLayout {
Label {
text: root.deviceClass.paramTypes.getParamType(model.id).displayName
}
Label {
Layout.fillWidth: true
text: model.value
horizontalAlignment: Text.AlignRight
}
paramType: root.deviceClass.paramTypes.getParamType(model.id)
param: root.device.params.get(index)
writable: false
}
}
Component {
id: errorDialog
ErrorDialog { }
}
}

View File

@ -42,6 +42,11 @@ Page {
height: app.iconSize
}
Label {
text: qsTr("Thing is not connected!")
visible: infoPane.connectedState !== null && infoPane.connectedState.value === false
}
ColorIcon {
height: app.iconSize
width: height
@ -54,6 +59,7 @@ Page {
height: app.iconSize
width: height * 1.23
name: infoPane.batteryState !== null ? "../images/battery/battery-" + ("00" + (Math.floor(infoPane.batteryState.value / 10) * 10)).slice(-3) + ".svg" : ""
visible: infoPane.batteryState !== null
}
}
}

View File

@ -27,7 +27,7 @@ DevicePageBase {
id: interfaceViewsRepeater
property bool unhandledInterface: false
model: deviceClass.interfaces
// model: deviceClass.interfaces
delegate: Loader {
id: stateViewLoader
Layout.fillWidth: true

View File

@ -10,6 +10,7 @@ Page {
property var device
readonly property var deviceClass: Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId)
property bool readOnly: true
header: GuhHeader {
text: "Details for " + root.device.name
@ -43,7 +44,7 @@ Page {
Layout.fillWidth: true
sourceComponent: {
var writable = deviceClass.actionTypes.getActionType(id) !== null;
if (!writable) {
if (root.readOnly || !writable) {
return labelComponent;
}
@ -58,6 +59,8 @@ Page {
return textFieldComponent;
case "String":
return textFieldComponent;
case "Color":
return colorPreviewComponent;
}
console.warn("DeviceStateDetailsPage: Type delegate not implemented", stateType.type)
return null;
@ -126,6 +129,18 @@ Page {
}
}
Component {
id: colorPreviewComponent
Rectangle {
property var value: "blue"
property var stateTypeId: null
color: value
implicitHeight: app.mediumFont
implicitWidth: height
radius: height / 4
}
}
function executeAction(stateTypeId, value) {
var paramList = []
var muteParam = {}

View File

@ -5,21 +5,8 @@ import Guh 1.0
import "../components"
import "../customviews"
Page {
DevicePageBase {
id: root
property var device: null
readonly property var deviceClass: Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId)
header: GuhHeader {
text: device.name
onBackPressed: pageStack.pop()
HeaderButton {
imageSource: "../images/info.svg"
onClicked: pageStack.push(Qt.resolvedUrl("GenericDeviceStateDetailsPage.qml"), {device: root.device})
}
}
ListView {
anchors { fill: parent }

View File

@ -1,132 +0,0 @@
import QtQuick 2.8
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.1
import "../components"
import Guh 1.0
Page {
id: root
property var rule: null
StackView {
id: internalPageStack
anchors.fill: parent
initialItem: newRulePage1
}
function addEventDescriptor() {
var eventDescriptor = root.rule.eventDescriptors.createNewEventDescriptor();
var page = internalPageStack.push(Qt.resolvedUrl("SelectThingPage.qml"));
page.onBackPressed.connect(function() { internalPageStack.pop(); });
page.onThingSelected.connect(function(device) {
eventDescriptor.deviceId = device.id;
selectEventDescriptorData(eventDescriptor)
})
page.onInterfaceSelected.connect(function(interfaceName) {
eventDescriptor.interfaceName = interfaceName;
selectEventDescriptorData(eventDescriptor)
})
}
function selectEventDescriptorData(eventDescriptor) {
var eventPage = internalPageStack.push(Qt.resolvedUrl("SelectEventPage.qml"), {text: "Select event", eventDescriptor: eventDescriptor});
eventPage.onBackPressed.connect(function() {internalPageStack.pop()})
eventPage.onDone.connect(function() {
root.rule.eventDescriptors.addEventDescriptor(eventPage.eventDescriptor);
internalPageStack.pop(newRulePage1)
})
}
function addAction() {
}
Page {
id: newRulePage1
header: GuhHeader {
text: "New rule"
onBackPressed: pageStack.pop()
}
ColumnLayout {
anchors.fill: parent
RowLayout {
Layout.fillWidth: true
RadioButton {
id: whenButton
text: "When"
checked: true
}
RadioButton {
id: whileButton
text: "While"
}
}
RowLayout {
Layout.fillWidth: true
visible: eventsRepeater.count == 0
Label {
Layout.fillWidth: true
text: "Add an event which should trigger the execution of the rule"
}
Button {
text: "+"
onClicked: root.addEventDescriptor();
}
}
Repeater {
id: eventsRepeater
model: root.rule.eventDescriptors
delegate: ItemDelegate {
id: eventDelegate
property var device: Engine.deviceManager.devices.getDevice(root.rule.eventDescriptors.get(index).deviceId)
property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
property var eventType: deviceClass ? deviceClass.eventTypes.getEventType(root.rule.eventDescriptors.get(index).eventTypeId) : null
contentItem: ColumnLayout {
Label {
text: eventDelegate.device ? eventDelegate.device.name : "Unknown device" + root.rule.eventDescriptors.get(index).deviceId
Layout.fillWidth: true
}
Label {
text: eventDelegate.eventType ? eventDelegate.eventType.displayName : "Unknown event" + root.rule.eventDescriptors.get(index).eventTypeId
}
}
}
}
Label {
text: "do the following:"
}
RowLayout {
Layout.fillWidth: true
visible: actionsRepeater.count == 0
Label {
Layout.fillWidth: true
text: "Add action which should be executed when the rule is triggered"
}
Button {
text: "+"
onClicked: root.addAction();
}
}
Repeater {
id: actionsRepeater
model: root.rule.actions
delegate: ItemDelegate {
id: actionDelegate
contentItem: ColumnLayout {
Label {
text: "bla"
}
}
}
}
}
}
}

View File

@ -2,7 +2,7 @@ import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import "../components"
import "../paramdelegates"
import "../paramdelegates-ng"
import Guh 1.0
Page {
@ -27,10 +27,8 @@ Page {
id: delegateRepeater
model: root.actionType.paramTypes
delegate: ParamDelegate {
width: parent.width
Layout.fillWidth: true
paramType: root.actionType.paramTypes.get(index)
value: paramType.defaultValue
}
}
Item {

View File

@ -0,0 +1,193 @@
import QtQuick 2.8
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.1
import QtQuick.Controls.Material 2.1
import Guh 1.0
import "../components"
ItemDelegate {
id: root
property var paramType: null
property alias value: d.value
property var param: Param {
id: d
paramTypeId: paramType.id
value: paramType.defaultValue
}
property bool writable: true
contentItem: ColumnLayout {
RowLayout {
Label {
Layout.fillWidth: true
text: root.paramType.displayName
elide: Text.ElideRight
}
Loader {
id: loader
Layout.fillWidth: sourceComponent == textFieldComponent
sourceComponent: {
if (!root.writable) {
return stringComponent;
}
switch (root.paramType.type) {
case "Bool":
return boolComponent;
case "Int":
return stringComponent;
case "String":
if (root.paramType.allowedValues.length > 0) {
return comboBoxComponent;
}
return textFieldComponent;
case "Color":
return colorPreviewComponent;
}
console.warn("Param Delegate: Fallback to stringComponent", root.paramType.name, root.paramType.type)
return stringComponent;
}
}
}
Loader {
Layout.fillWidth: true
sourceComponent: {
switch (root.paramType.type) {
case "Int":
case "Double":
if (root.paramType.minValue != undefined && root.paramType.maxValue != undefined) {
return sliderComponent
}
break;
case "Color":
return colorPickerComponent
}
return null;
}
}
}
Component {
id: stringComponent
Label {
text: {
switch (root.paramType.type) {
case "Int":
return Math.round(root.param.value);
}
return root.param.value;
}
}
}
Component {
id: boolComponent
Switch {
checked: root.param.value === true
onClicked: {
root.param.value = checked;
}
}
}
Component {
id: sliderComponent
RowLayout {
spacing: app.margins
Label {
text: root.paramType.minValue
}
Slider {
Layout.fillWidth: true
from: root.paramType.minValue
to: root.paramType.maxValue
value: root.param.value
stepSize: {
switch (root.paramType.type) {
case "Int":
return 1;
}
return 0.01;
}
onMoved: {
root.param.value = value;
}
}
Label {
text: root.paramType.maxValue
}
}
}
Component {
id: textFieldComponent
TextField {
text: root.param.value
onEditingFinished: {
root.param.value = text
}
}
}
Component {
id: comboBoxComponent
ComboBox {
model: root.paramType.allowedValues
currentIndex: root.paramType.allowedValues.indexOf(root.param.value)
onActivated: {
root.param.value = root.paramType.allowedValues[index]
print("setting value to", root.param.value)
}
}
}
Component {
id: colorPickerComponent
ColorPicker {
id: colorPicker
implicitHeight: 200
// color: root.param.value
Binding {
target: colorPicker
property: "color"
value: root.param.value
when: !colorPicker.pressed
}
onColorChanged: {
root.param.value = color;
}
touchDelegate: Rectangle {
height: 15
width: height
radius: height / 2
color: Material.accent
Rectangle {
color: colorPicker.hovered || colorPicker.pressed ? "#11000000" : "transparent"
anchors.centerIn: parent
height: 30
width: height
radius: width / 2
Behavior on color { ColorAnimation { duration: 200 } }
}
}
}
}
Component {
id: colorPreviewComponent
Rectangle {
implicitHeight: app.mediumFont
implicitWidth: implicitHeight
color: root.param.value
radius: width / 4
}
}
}

View File

@ -2,19 +2,20 @@ import QtQuick 2.8
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.1
RowLayout {
ParamDelegateBase {
id: root
property alias text: label.text
property alias value: theSwitch.checked
contentItem: RowLayout {
Label {
id: label
Layout.fillWidth: true
text: root.paramType.displayName + "- " + root.value
}
Switch {
id: theSwitch
checked: root.value === true
checked: root.value == true
onClicked: root.value = checked
}
}
}

View File

@ -10,7 +10,7 @@ ParamDelegateBase {
Label {
id: label
text: root.paramType.name
text: root.paramType.displayName
}
TextField {
id: textField

View File

@ -10,16 +10,16 @@ ParamDelegateBase {
Label {
id: label
text: root.paramType.name
text: root.paramType.displayName
Layout.fillWidth: true
}
TextField {
id: textField
Layout.fillWidth: true
text: root.value ? root.value : root.paramType.defaultValue
Layout.preferredWidth: implicitWidth
onTextChanged: {
root.value = text;
}
}
}
}

View File

@ -5,21 +5,20 @@ import Guh 1.0
ItemDelegate {
id: root
height: layout.height
property var paramType: null
property var value: null
property int operatorType: ParamDescriptors.ValueOperatorEquals
contentItem: ColumnLayout {
RowLayout {
id: layout
anchors { left: parent.left; top: parent.top; right: parent.right}
anchors.margins: app.margins
Layout.fillWidth: true
spacing: app.margins
Label {
text: paramType.displayName
}
ComboBox {
Layout.fillWidth: true
model: {
switch (paramType.type) {
case "Bool":
@ -55,9 +54,11 @@ ItemDelegate {
}
}
Loader {
id: placeHolder
Layout.fillWidth: true
sourceComponent: {
print("Datatye is:", paramType.type, paramType.minValue, paramType.maxValue)
switch (paramType.type) {
@ -66,7 +67,12 @@ ItemDelegate {
case "Int":
case "Double":
if (paramType.minValue !== undefined && paramType.maxValue !== undefined) {
return sliderComponent;
return labelComponent;
}
return textFieldComponent;
case "String":
if (paramType.allowedValues.length > 0) {
return comboBoxComponent
}
return textFieldComponent;
}
@ -74,7 +80,35 @@ ItemDelegate {
return null;
}
}
}
Loader {
Layout.fillWidth: true
sourceComponent: {
switch (paramType.type) {
case "Int":
case "Double":
if (paramType.minValue !== undefined && paramType.maxValue !== undefined) {
return sliderComponent
}
}
}
}
}
Component {
id: labelComponent
Label {
text: {
switch (root.paramType.type) {
case "Int":
return Math.round(root.value)
}
return root.value
}
}
}
Component {
@ -89,13 +123,20 @@ ItemDelegate {
Component {
id: sliderComponent
RowLayout {
spacing: app.margins
Label { text: root.paramType.minValue }
Slider {
from: paramType.minValue
to: paramType.maxValue
Layout.fillWidth: true
onMoved: {
root.value = value;
}
}
Label { text: root.paramType.maxValue }
}
}
Component {
@ -110,4 +151,15 @@ ItemDelegate {
}
}
}
Component {
id: comboBoxComponent
ComboBox {
model: paramType.allowedValues
currentIndex: root.paramType.value
onActivated: {
root.value = paramType.allowedValues[index]
}
}
}
}

View File

@ -49,10 +49,10 @@ Page {
clip: true
headerPositioning: ListView.OverlayHeader
property int column0Width: root.width / 10 * 3
property int column0Width: root.width / 10 * 2
property int column1Width: root.width / 10 * 1
property int column2Width: root.width / 10 * 3
property int column3Width: root.width / 10 * 2
property int column3Width: root.width / 10 * 3
property int column4Width: root.width / 10 * 1
header: Rectangle {
@ -97,7 +97,7 @@ Page {
property var deviceClass: device ? Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
Label {
width: listView.column0Width
text: Qt.formatDateTime(model.timestamp,"dd.MM.yy - hh:mm:ss")
text: width > 130 ? Qt.formatDateTime(model.timestamp,"dd.MM.yy - hh:mm:ss") : Qt.formatDateTime(model.timestamp,"hh:mm:ss")
elide: Text.ElideRight
}
Label {

View File

@ -0,0 +1,63 @@
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Controls.Material 2.1
import QtQuick.Layouts 1.3
import "../components"
import "../paramdelegates-ng"
import Guh 1.0
Page {
id: root
property var plugin: null
header: GuhHeader {
text: qsTr("%1 settings").arg(plugin.name)
backButtonVisible: true
onBackPressed: pageStack.pop()
HeaderButton {
imageSource: "../images/tick.svg"
onClicked: {
Engine.deviceManager.savePluginConfig(root.plugin.pluginId)
}
}
}
Connections {
target: Engine.deviceManager
onSavePluginConfigReply: {
if (params.params.deviceError == "DeviceErrorNoError") {
pageStack.pop();
} else {
console.warn("Error saving plugin params:", JSON.stringify(params))
var dialog = errorDialog.createObject(root, {title: "Error", text: "Error saving params: " + JSON.stringify(params.params.deviceError)});
dialog.open();
}
}
}
Flickable {
anchors.fill: parent
contentHeight: column.implicitHeight
ColumnLayout {
id: column
width: parent.width
Repeater {
model: plugin.paramTypes
delegate: ParamDelegate {
Layout.fillWidth: true
paramType: root.plugin.paramTypes.get(index)
param: root.plugin.params.getParam(model.id)
}
}
}
}
Component {
id: errorDialog
ErrorDialog { }
}
}

View File

@ -0,0 +1,38 @@
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Controls.Material 2.1
import QtQuick.Layouts 1.3
import "../components"
import Guh 1.0
Page {
id: root
header: GuhHeader {
text: "Plugins"
backButtonVisible: true
onBackPressed: pageStack.pop()
}
ListView {
anchors.fill: parent
model: Engine.deviceManager.plugins
clip: true
delegate: ItemDelegate {
width: parent.width
contentItem: RowLayout {
Label {
Layout.fillWidth: true
text: model.name
}
Image {
source: "../images/next.svg"
Layout.preferredHeight: parent.height
Layout.preferredWidth: height
}
}
onClicked: pageStack.push(Qt.resolvedUrl("PluginParamsPage.qml"), {plugin: Engine.deviceManager.plugins.get(index)})
}
}
}

View File

@ -22,22 +22,24 @@
#include "param.h"
Param::Param(const QString &id, const QVariant &value, QObject *parent) :
Param::Param(const QString &paramTypeId, const QVariant &value, QObject *parent) :
QObject(parent),
m_id(id),
m_paramTypeId(paramTypeId),
m_value(value)
{
}
QString Param::id() const
QString Param::paramTypeId() const
{
return m_id;
return m_paramTypeId;
}
void Param::setId(const QString &id)
void Param::setParamTypeId(const QString &paramTypeId)
{
m_id = id;
emit idChanged();
if (m_paramTypeId != paramTypeId) {
m_paramTypeId = paramTypeId;
emit paramTypeIdChanged();
}
}
QVariant Param::value() const

View File

@ -30,24 +30,24 @@
class Param : public QObject
{
Q_OBJECT
Q_PROPERTY(QString id READ id WRITE setId NOTIFY idChanged)
Q_PROPERTY(QString paramTypeId READ paramTypeId WRITE setParamTypeId NOTIFY paramTypeIdChanged)
Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
public:
Param(const QString &id = QString(), const QVariant &value = QVariant(), QObject *parent = 0);
Param(const QString &paramTypeId = QString(), const QVariant &value = QVariant(), QObject *parent = 0);
QString id() const;
void setId(const QString &id);
QString paramTypeId() const;
void setParamTypeId(const QString &paramTypeId);
QVariant value() const;
void setValue(const QVariant &value);
private:
QString m_id;
QString m_paramTypeId;
QVariant m_value;
signals:
void idChanged();
void paramTypeIdChanged();
void valueChanged();
};

View File

@ -20,7 +20,7 @@ void ParamDescriptor::setOperatorType(ParamDescriptor::ValueOperator operatorTyp
ParamDescriptor *ParamDescriptor::clone() const
{
ParamDescriptor *ret = new ParamDescriptor(this->id(), this->value());
ParamDescriptor *ret = new ParamDescriptor(this->paramTypeId(), this->value());
ret->setOperatorType(this->operatorType());
return ret;
}

View File

@ -16,7 +16,7 @@ QVariant ParamDescriptors::data(const QModelIndex &index, int role) const
{
switch (role) {
case RoleId:
return m_list.at(index.row())->id();
return m_list.at(index.row())->paramTypeId();
case RoleValue:
return m_list.at(index.row())->value();
case RoleOperator:
@ -56,7 +56,7 @@ void ParamDescriptors::addParamDescriptor(ParamDescriptor *paramDescriptor)
void ParamDescriptors::setParamDescriptor(const QString &paramTypeId, const QVariant &value, ValueOperator operatorType)
{
foreach (ParamDescriptor* paramDescriptor, m_list) {
if (paramDescriptor->id() == paramTypeId) {
if (paramDescriptor->paramTypeId() == paramTypeId) {
paramDescriptor->setValue(value);
paramDescriptor->setOperatorType((ParamDescriptor::ValueOperator)operatorType);
return;
@ -64,7 +64,7 @@ void ParamDescriptors::setParamDescriptor(const QString &paramTypeId, const QVar
}
// Still here? need to add a new one
ParamDescriptor* paramDescriptor = createNewParamDescriptor();
paramDescriptor->setId(paramTypeId);
paramDescriptor->setParamTypeId(paramTypeId);
paramDescriptor->setValue(value);
paramDescriptor->setOperatorType((ParamDescriptor::ValueOperator)operatorType);
addParamDescriptor(paramDescriptor);

View File

@ -47,7 +47,7 @@ Param *Params::get(int index) const
Param *Params::getParam(QString paramTypeId) const
{
foreach (Param *param, m_params) {
if (param->id() == paramTypeId) {
if (param->paramTypeId() == paramTypeId) {
return param;
}
}
@ -72,7 +72,7 @@ QVariant Params::data(const QModelIndex &index, int role) const
Param *param = m_params.at(index.row());
if (role == RoleId) {
return param->id();
return param->paramTypeId();
} else if (role == RoleValue) {
return param->value();
}

View File

@ -71,6 +71,10 @@ QVariant ParamTypes::data(const QModelIndex &index, int role) const
ParamType *paramType = m_paramTypes.at(index.row());
if (role == NameRole) {
return paramType->name();
} else if (role == DisplayNameRole) {
return paramType->displayName();
} else if (role == IdRole) {
return paramType->id();
} else if (role == TypeRole) {
return paramType->type();
} else if (role == DefaultValueRole) {
@ -111,7 +115,9 @@ void ParamTypes::clearModel()
QHash<int, QByteArray> ParamTypes::roleNames() const
{
QHash<int, QByteArray> roles;
roles[IdRole] = "id";
roles[NameRole] = "name";
roles[DisplayNameRole] = "displayName";
roles[TypeRole] = "type";
roles[MinValueRole] = "minValue";
roles[MaxValueRole] = "maxValue";

View File

@ -34,6 +34,8 @@ class ParamTypes : public QAbstractListModel
public:
enum ParamTypeRole {
NameRole = Qt::DisplayRole,
DisplayNameRole,
IdRole,
TypeRole,
DefaultValueRole,
MinValueRole,

View File

@ -24,7 +24,7 @@
Plugin::Plugin(QObject *parent) : QObject(parent)
{
m_params = new Params(this);
}
QString Plugin::name() const

View File

@ -55,8 +55,8 @@ public:
private:
QString m_name;
QUuid m_pluginId;
ParamTypes *m_paramTypes;
Params *m_params;
ParamTypes *m_paramTypes = nullptr;
Params *m_params = nullptr;
};
#endif // PLUGIN_H