improve groups view
This commit is contained in:
parent
37397e2c65
commit
14c7a3de1e
@ -137,6 +137,7 @@ void Engine::onConnectedChanged()
|
|||||||
qDebug() << "Engine: connected changed:" << m_jsonRpcClient->connected();
|
qDebug() << "Engine: connected changed:" << m_jsonRpcClient->connected();
|
||||||
m_deviceManager->clear();
|
m_deviceManager->clear();
|
||||||
m_ruleManager->clear();
|
m_ruleManager->clear();
|
||||||
|
m_tagsManager->clear();
|
||||||
if (m_jsonRpcClient->connected()) {
|
if (m_jsonRpcClient->connected()) {
|
||||||
qDebug() << "Engine: inital setup required:" << m_jsonRpcClient->initialSetupRequired() << "auth required:" << m_jsonRpcClient->authenticationRequired();
|
qDebug() << "Engine: inital setup required:" << m_jsonRpcClient->initialSetupRequired() << "auth required:" << m_jsonRpcClient->authenticationRequired();
|
||||||
if (!m_jsonRpcClient->initialSetupRequired() && !m_jsonRpcClient->authenticationRequired()) {
|
if (!m_jsonRpcClient->initialSetupRequired() && !m_jsonRpcClient->authenticationRequired()) {
|
||||||
|
|||||||
@ -23,6 +23,11 @@ void TagsManager::init()
|
|||||||
m_jsonClient->sendCommand("Tags.GetTags", this, "getTagsReply");
|
m_jsonClient->sendCommand("Tags.GetTags", this, "getTagsReply");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TagsManager::clear()
|
||||||
|
{
|
||||||
|
m_tags->clear();
|
||||||
|
}
|
||||||
|
|
||||||
bool TagsManager::busy() const
|
bool TagsManager::busy() const
|
||||||
{
|
{
|
||||||
return m_busy;
|
return m_busy;
|
||||||
@ -123,7 +128,6 @@ void TagsManager::getTagsReply(const QVariantMap ¶ms)
|
|||||||
{
|
{
|
||||||
QList<Tag*> tags;
|
QList<Tag*> tags;
|
||||||
foreach (const QVariant &tagVariant, params.value("params").toMap().value("tags").toList()) {
|
foreach (const QVariant &tagVariant, params.value("params").toMap().value("tags").toList()) {
|
||||||
qDebug() << "aDDING TAG";
|
|
||||||
Tag *tag = unpackTag(tagVariant.toMap());
|
Tag *tag = unpackTag(tagVariant.toMap());
|
||||||
if (tag) {
|
if (tag) {
|
||||||
tags.append(tag);
|
tags.append(tag);
|
||||||
|
|||||||
@ -17,6 +17,7 @@ public:
|
|||||||
QString nameSpace() const override;
|
QString nameSpace() const override;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
void clear();
|
||||||
bool busy() const;
|
bool busy() const;
|
||||||
|
|
||||||
Tags* tags() const;
|
Tags* tags() const;
|
||||||
|
|||||||
@ -120,6 +120,13 @@ Interfaces::Interfaces(QObject *parent) : QAbstractListModel(parent)
|
|||||||
tr("Playback status"),
|
tr("Playback status"),
|
||||||
tr("Playback status changed"),
|
tr("Playback status changed"),
|
||||||
tr("Set playback status"));
|
tr("Set playback status"));
|
||||||
|
|
||||||
|
addInterface("mediacontroller", tr("Media controllers"));
|
||||||
|
addActionType("mediacontroller", "play", tr("Start playback"), new ParamTypes());
|
||||||
|
addActionType("mediacontroller", "stop", tr("Stop playback"), new ParamTypes());
|
||||||
|
addActionType("mediacontroller", "pause", tr("Pause playback"), new ParamTypes());
|
||||||
|
addActionType("mediacontroller", "skipBack", tr("Skip back"), new ParamTypes());
|
||||||
|
addActionType("mediacontroller", "skipNext", tr("Skip next"), new ParamTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
int Interfaces::rowCount(const QModelIndex &parent) const
|
int Interfaces::rowCount(const QModelIndex &parent) const
|
||||||
@ -149,6 +156,9 @@ QHash<int, QByteArray> Interfaces::roleNames() const
|
|||||||
|
|
||||||
Interface *Interfaces::get(int index) const
|
Interface *Interfaces::get(int index) const
|
||||||
{
|
{
|
||||||
|
if (index < 0 || index >= m_list.count()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return m_list.at(index);
|
return m_list.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -199,5 +199,6 @@
|
|||||||
<file>ui/magic/NewScenePage.qml</file>
|
<file>ui/magic/NewScenePage.qml</file>
|
||||||
<file>ui/mainviews/GroupsView.qml</file>
|
<file>ui/mainviews/GroupsView.qml</file>
|
||||||
<file>ui/grouping/GroupPage.qml</file>
|
<file>ui/grouping/GroupPage.qml</file>
|
||||||
|
<file>ui/delegates/ThingTile.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -299,7 +299,7 @@ Page {
|
|||||||
|
|
||||||
GroupsView {
|
GroupsView {
|
||||||
id: groupsView
|
id: groupsView
|
||||||
property string title: qsTr("My groups" + count);
|
property string title: qsTr("My groups");
|
||||||
width: swipeView.width
|
width: swipeView.width
|
||||||
height: swipeView.height
|
height: swipeView.height
|
||||||
}
|
}
|
||||||
|
|||||||
376
nymea-app/ui/delegates/ThingTile.qml
Normal file
376
nymea-app/ui/delegates/ThingTile.qml
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import QtQuick.Controls.Material 2.2
|
||||||
|
import Nymea 1.0
|
||||||
|
import "../components"
|
||||||
|
|
||||||
|
MainPageTile {
|
||||||
|
id: root
|
||||||
|
text: device.name.toUpperCase()
|
||||||
|
iconName: app.interfacesToIcon(deviceClass.interfaces)
|
||||||
|
iconColor: app.accentColor
|
||||||
|
batteryCritical: batteryCriticalState && batteryCriticalState.value === true
|
||||||
|
disconnected: connectedState && connectedState.value === false
|
||||||
|
|
||||||
|
backgroundImage: artworkState && artworkState.value.length > 0 ? artworkState.value : ""
|
||||||
|
|
||||||
|
property Device device: null
|
||||||
|
readonly property DeviceClass deviceClass: device ? engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
||||||
|
readonly property State connectedState: deviceClass.interfaces.indexOf("connectable") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("connected").id) : null
|
||||||
|
readonly property State batteryCriticalState: deviceClass.interfaces.indexOf("battery") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("batteryCritical").id) : null
|
||||||
|
readonly property State artworkState: deviceClass.interfaces.indexOf("mediametadataprovider") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("artwork").id) : null
|
||||||
|
|
||||||
|
contentItem: Loader {
|
||||||
|
id: loader
|
||||||
|
anchors.fill: parent
|
||||||
|
sourceComponent: {
|
||||||
|
if (root.deviceClass.interfaces.indexOf("closable") >= 0) {
|
||||||
|
return closableComponent;
|
||||||
|
}
|
||||||
|
if (root.deviceClass.interfaces.indexOf("power") >= 0) {
|
||||||
|
return lightsComponent;
|
||||||
|
}
|
||||||
|
if (root.deviceClass.interfaces.indexOf("sensor") >= 0) {
|
||||||
|
return sensorsComponent;
|
||||||
|
}
|
||||||
|
if (root.deviceClass.interfaces.indexOf("weather") >= 0) {
|
||||||
|
return sensorsComponent;
|
||||||
|
}
|
||||||
|
if (root.deviceClass.interfaces.indexOf("smartmeter") >= 0) {
|
||||||
|
return sensorsComponent;
|
||||||
|
}
|
||||||
|
if (root.deviceClass.interfaces.indexOf("mediacontroller") >= 0) {
|
||||||
|
return mediaComponent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Binding { target: loader.item ? loader.item : null; property: "deviceClass"; value: root.deviceClass }
|
||||||
|
Binding { target: loader.item ? loader.item : null; property: "device"; value: root.device }
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: lightsComponent
|
||||||
|
RowLayout {
|
||||||
|
property var device: null
|
||||||
|
property var deviceClass: null
|
||||||
|
|
||||||
|
readonly property var powerStateType: deviceClass.stateTypes.findByName("power");
|
||||||
|
readonly property var powerState: device.states.getState(powerStateType.id)
|
||||||
|
|
||||||
|
readonly property var brightnessStateType: deviceClass.stateTypes.findByName("brightness");
|
||||||
|
readonly property var brightnessState: brightnessStateType ? device.states.getState(brightnessStateType.id) : null
|
||||||
|
|
||||||
|
ThrottledSlider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: app.margins / 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
opacity: deviceClass.interfaces.indexOf("dimmablelight") >= 0 ? 1 : 0
|
||||||
|
enabled: opacity > 0
|
||||||
|
from: 0
|
||||||
|
to: 100
|
||||||
|
value: brightnessState ? brightnessState.value : 0
|
||||||
|
onMoved: {
|
||||||
|
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||||
|
var actionType = deviceClass.actionTypes.findByName("brightness");
|
||||||
|
var params = [];
|
||||||
|
var powerParam = {}
|
||||||
|
powerParam["paramTypeId"] = actionType.paramTypes.get(0).id;
|
||||||
|
powerParam["value"] = value;
|
||||||
|
params.push(powerParam)
|
||||||
|
engine.deviceManager.executeAction(device.id, actionType.id, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemDelegate {
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
Layout.preferredHeight: width
|
||||||
|
Layout.rightMargin: app.margins / 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
padding: 0; topPadding: 0; bottomPadding: 0
|
||||||
|
|
||||||
|
contentItem: ColorIcon {
|
||||||
|
name: deviceClass.interfaces.indexOf("light") >= 0
|
||||||
|
? (powerState.value === true ? "../images/light-on.svg" : "../images/light-off.svg")
|
||||||
|
: app.interfacesToIcon(deviceClass.interfaces)
|
||||||
|
color: powerState.value === true ? app.accentColor : keyColor
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||||
|
var actionType = deviceClass.actionTypes.findByName("power");
|
||||||
|
var params = [];
|
||||||
|
var powerParam = {}
|
||||||
|
powerParam["paramTypeId"] = actionType.paramTypes.get(0).id;
|
||||||
|
powerParam["value"] = !powerState.value;
|
||||||
|
params.push(powerParam)
|
||||||
|
engine.deviceManager.executeAction(device.id, actionType.id, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: sensorsComponent
|
||||||
|
RowLayout {
|
||||||
|
id: sensorsRoot
|
||||||
|
property var device: null
|
||||||
|
property var deviceClass: null
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
property var shownInterfaces: []
|
||||||
|
property int currentStateIndex: -1
|
||||||
|
property var currentStateType: deviceClass ? deviceClass.stateTypes.findByName(shownInterfaces[currentStateIndex].state) : null
|
||||||
|
property var currentState: currentStateType ? device.states.getState(currentStateType.id) : null
|
||||||
|
|
||||||
|
onDeviceClassChanged: {
|
||||||
|
if (deviceClass == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmp = []
|
||||||
|
if (deviceClass.interfaces.indexOf("temperaturesensor") >= 0) {
|
||||||
|
tmp.push({iface: "temperaturesensor", state: "temperature"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("humiditysensor") >= 0) {
|
||||||
|
tmp.push({iface: "humiditysensor", state: "humidity"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("moisturesensor") >= 0) {
|
||||||
|
tmp.push({iface: "moisturesensor", state: "moisture"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("pressuresensor") >= 0) {
|
||||||
|
tmp.push({iface: "pressuresensor", state: "pressure"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("lightsensor") >= 0) {
|
||||||
|
tmp.push({iface: "lightsensor", state: "lightIntensity"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("conductivitysensor") >= 0) {
|
||||||
|
tmp.push({iface: "conductivitysensor", state: "conductivity"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("noisesensor") >= 0) {
|
||||||
|
tmp.push({iface: "noisesensor", state: "noise"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("co2sensor") >= 0) {
|
||||||
|
tmp.push({iface: "co2sensor", state: "co2"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("smartmeterconsumer") >= 0) {
|
||||||
|
tmp.push({iface: "smartmeterconsumer", state: "totalEnergyConsumed"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("smartmeterproducer") >= 0) {
|
||||||
|
tmp.push({iface: "smartmeterproducer", state: "totalEnergyProduced"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("daylightsensor") >= 0) {
|
||||||
|
tmp.push({iface: "daylightsensor", state: "daylight"});
|
||||||
|
}
|
||||||
|
if (deviceClass.interfaces.indexOf("presencesensor") >= 0) {
|
||||||
|
tmp.push({iface: "presencesensor", state: "isPresent"});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceClass.interfaces.indexOf("weather") >= 0) {
|
||||||
|
tmp.push({iface: "temperaturesensor", state: "temperature"});
|
||||||
|
tmp.push({iface: "humiditysensor", state: "humidity"});
|
||||||
|
tmp.push({iface: "pressuresensor", state: "pressure"});
|
||||||
|
}
|
||||||
|
|
||||||
|
shownInterfaces = tmp
|
||||||
|
currentStateIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemDelegate {
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
Layout.preferredHeight: width
|
||||||
|
Layout.leftMargin: app.margins / 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
padding: 0; topPadding: 0; bottomPadding: 0
|
||||||
|
visible: sensorsRoot.shownInterfaces.length > 1
|
||||||
|
contentItem: ColorIcon {
|
||||||
|
name: "../images/back.svg"
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
var newIndex = sensorsRoot.currentStateIndex - 1;
|
||||||
|
if (newIndex < 0) newIndex = sensorsRoot.shownInterfaces.length - 1
|
||||||
|
sensorsRoot.currentStateIndex = newIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillHeight: true; Layout.fillWidth: true }
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
Layout.preferredHeight: width
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
color: app.interfaceToColor(sensorsRoot.shownInterfaces[sensorsRoot.currentStateIndex].iface)
|
||||||
|
name: app.interfaceToIcon(sensorsRoot.shownInterfaces[sensorsRoot.currentStateIndex].iface)
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillHeight: true; Layout.fillWidth: true }
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 0
|
||||||
|
visible: sensorsRoot.currentStateType.type.toLowerCase() !== "bool"
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
text: sensorsRoot.currentStateType.unitString
|
||||||
|
font.pixelSize: app.smallFont
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
text: sensorsRoot.currentState.value// + " " + sensorsRoot.currentStateType.unitString
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Led {
|
||||||
|
state: sensorsRoot.currentState.value === true ? "on" : "off"
|
||||||
|
visible: sensorsRoot.currentStateType.type.toLowerCase() === "bool"
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillHeight: true; Layout.fillWidth: true }
|
||||||
|
|
||||||
|
ItemDelegate {
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
Layout.preferredHeight: width
|
||||||
|
Layout.rightMargin: app.margins / 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
padding: 0; topPadding: 0; bottomPadding: 0
|
||||||
|
visible: sensorsRoot.shownInterfaces.length > 1
|
||||||
|
contentItem: ColorIcon {
|
||||||
|
name: "../images/next.svg"
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
var newIndex = sensorsRoot.currentStateIndex + 1;
|
||||||
|
if (newIndex >= sensorsRoot.shownInterfaces.length) newIndex = 0;
|
||||||
|
sensorsRoot.currentStateIndex = newIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: closableComponent
|
||||||
|
RowLayout {
|
||||||
|
property var device: null
|
||||||
|
property var deviceClass: null
|
||||||
|
|
||||||
|
ItemDelegate {
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
Layout.preferredHeight: width
|
||||||
|
Layout.leftMargin: app.margins / 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
padding: 0; topPadding: 0; bottomPadding: 0
|
||||||
|
contentItem: ColorIcon {
|
||||||
|
name: "../images/up.svg"
|
||||||
|
color: app.accentColor
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||||
|
var actionType = deviceClass.actionTypes.findByName("open");
|
||||||
|
engine.deviceManager.executeAction(device.id, actionType.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Slider {
|
||||||
|
id: closableSlider
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
visible: deviceClass.interfaces.indexOf("extendedclosable") >= 0
|
||||||
|
readonly property var percentageStateType: deviceClass.stateTypes.findByName("percentage");
|
||||||
|
readonly property var percentateState: percentageStateType ? device.states.getState(percentageStateType.id) : null
|
||||||
|
from: 0
|
||||||
|
to: 100
|
||||||
|
value: percentateState ? percentateState.value : 0
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
visible: !closableSlider.visible
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemDelegate {
|
||||||
|
Layout.preferredWidth: app.iconSize
|
||||||
|
Layout.preferredHeight: width
|
||||||
|
Layout.rightMargin: app.margins / 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
padding: 0; topPadding: 0; bottomPadding: 0
|
||||||
|
contentItem: ColorIcon {
|
||||||
|
name: "../images/down.svg"
|
||||||
|
color: app.accentColor
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
||||||
|
var actionType = deviceClass.actionTypes.findByName("close");
|
||||||
|
engine.deviceManager.executeAction(device.id, actionType.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: mediaComponent
|
||||||
|
RowLayout {
|
||||||
|
id: mediaRoot
|
||||||
|
|
||||||
|
property Device device: null
|
||||||
|
property DeviceClass deviceClass: null
|
||||||
|
|
||||||
|
readonly property State playbackState: device.states.getState(deviceClass.stateTypes.findByName("playbackStatus").id)
|
||||||
|
|
||||||
|
function executeAction(actionName, params) {
|
||||||
|
var actionTypeId = deviceClass.actionTypes.findByName(actionName).id;
|
||||||
|
engine.deviceManager.executeAction(device.id, actionTypeId, params)
|
||||||
|
}
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
|
||||||
|
ProgressButton {
|
||||||
|
Layout.preferredHeight: app.iconSize * .9
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
imageSource: "../images/media-skip-backward.svg"
|
||||||
|
longpressImageSource: "../images/media-seek-backward.svg"
|
||||||
|
repeat: true
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
mediaRoot.executeAction("skipBack")
|
||||||
|
}
|
||||||
|
onLongpressed: {
|
||||||
|
mediaRoot.executeAction("fastRewind")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
|
||||||
|
ProgressButton {
|
||||||
|
Layout.preferredHeight: app.iconSize * 1.3
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
imageSource: mediaRoot.playbackState.value === "Playing" ? "../images/media-playback-pause.svg" : "../images/media-playback-start.svg"
|
||||||
|
longpressImageSource: "../images/media-playback-stop.svg"
|
||||||
|
longpressEnabled: mediaRoot.playbackState.value !== "Stopped"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (mediaRoot.playbackState.value === "Playing") {
|
||||||
|
mediaRoot.executeAction("pause")
|
||||||
|
} else {
|
||||||
|
mediaRoot.executeAction("play")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLongpressed: {
|
||||||
|
mediaRoot.executeAction("stop")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
ProgressButton {
|
||||||
|
Layout.preferredHeight: app.iconSize * .9
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
imageSource: "../images/media-skip-forward.svg"
|
||||||
|
longpressImageSource: "../images/media-seek-forward.svg"
|
||||||
|
repeat: true
|
||||||
|
onClicked: {
|
||||||
|
mediaRoot.executeAction("skipNext")
|
||||||
|
}
|
||||||
|
onLongpressed: {
|
||||||
|
mediaRoot.executeAction("fastForward")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -93,7 +93,6 @@ Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function addToGroup() {
|
function addToGroup() {
|
||||||
// engine.tagsManager.tagDevice(root.device.id, "group", "My group 1")
|
|
||||||
var dialog = addToGroupDialog.createObject(root)
|
var dialog = addToGroupDialog.createObject(root)
|
||||||
dialog.open();
|
dialog.open();
|
||||||
}
|
}
|
||||||
@ -122,6 +121,9 @@ Page {
|
|||||||
headerIcon: "../images/view-grid-symbolic.svg"
|
headerIcon: "../images/view-grid-symbolic.svg"
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
Layout.leftMargin: app.margins
|
||||||
|
Layout.rightMargin: app.margins
|
||||||
|
spacing: app.margins
|
||||||
TextField {
|
TextField {
|
||||||
id: newGroupdTextField
|
id: newGroupdTextField
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@ -141,6 +143,8 @@ Page {
|
|||||||
ListView {
|
ListView {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
height: 200
|
height: 200
|
||||||
|
clip: true
|
||||||
|
ScrollIndicator.vertical: ScrollIndicator {}
|
||||||
|
|
||||||
model: TagListModel {
|
model: TagListModel {
|
||||||
id: groupTags
|
id: groupTags
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import QtQuick.Controls.Material 2.1
|
|||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
import Nymea 1.0
|
import Nymea 1.0
|
||||||
import "../components"
|
import "../components"
|
||||||
|
import "../delegates"
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
id: root
|
id: root
|
||||||
@ -27,11 +28,28 @@ Page {
|
|||||||
showStates: true
|
showStates: true
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
GridView {
|
||||||
|
id: gridView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
anchors.margins: app.margins / 2
|
||||||
|
|
||||||
model: devicesInGroup
|
model: devicesInGroup
|
||||||
delegate: Label {
|
|
||||||
text: model.name
|
readonly property int minTileWidth: 180
|
||||||
|
readonly property int minTileHeight: 240
|
||||||
|
readonly property int tilesPerRow: root.width / minTileWidth
|
||||||
|
|
||||||
|
cellWidth: gridView.width / tilesPerRow
|
||||||
|
cellHeight: cellWidth
|
||||||
|
|
||||||
|
delegate: ThingTile {
|
||||||
|
width: gridView.cellWidth
|
||||||
|
height: gridView.cellHeight
|
||||||
|
|
||||||
|
device: devicesInGroup.get(index)
|
||||||
|
|
||||||
|
onClicked: pageStack.push(Qt.resolvedUrl("../devicepages/" + app.interfaceListToDevicePage(deviceClass.interfaces)), {device: device})
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,11 +5,15 @@ import QtQuick.Layouts 1.2
|
|||||||
import Nymea 1.0
|
import Nymea 1.0
|
||||||
import "../components"
|
import "../components"
|
||||||
|
|
||||||
Item {
|
MouseArea {
|
||||||
id: root
|
id: root
|
||||||
property alias count: interfacesGridView.count
|
property alias count: interfacesGridView.count
|
||||||
property alias model: interfacesGridView.model
|
property alias model: interfacesGridView.model
|
||||||
|
|
||||||
|
// Prevent scroll events to swipe left/right in case they fall through the grid
|
||||||
|
preventStealing: true
|
||||||
|
onWheel: wheel.accepted = true
|
||||||
|
|
||||||
GridView {
|
GridView {
|
||||||
id: interfacesGridView
|
id: interfacesGridView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|||||||
@ -4,13 +4,18 @@ import QtQuick.Layouts 1.3
|
|||||||
import QtQuick.Controls.Material 2.2
|
import QtQuick.Controls.Material 2.2
|
||||||
import Nymea 1.0
|
import Nymea 1.0
|
||||||
import "../components"
|
import "../components"
|
||||||
|
import "../delegates"
|
||||||
|
|
||||||
Item {
|
MouseArea {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool editMode: false
|
property bool editMode: false
|
||||||
readonly property int count: tagsProxy.count
|
readonly property int count: tagsProxy.count
|
||||||
|
|
||||||
|
// Prevent scroll events to swipe left/right in case they fall through the grid
|
||||||
|
preventStealing: true
|
||||||
|
onWheel: wheel.accepted = true
|
||||||
|
|
||||||
TagsProxyModel {
|
TagsProxyModel {
|
||||||
id: tagsProxy
|
id: tagsProxy
|
||||||
tags: engine.tagsManager.tags
|
tags: engine.tagsManager.tags
|
||||||
@ -29,57 +34,16 @@ Item {
|
|||||||
cellHeight: cellWidth
|
cellHeight: cellWidth
|
||||||
|
|
||||||
model: tagsProxy
|
model: tagsProxy
|
||||||
delegate: MainPageTile {
|
delegate: ThingTile {
|
||||||
id: delegateRoot
|
id: delegateRoot
|
||||||
width: gridView.cellWidth
|
width: gridView.cellWidth
|
||||||
height: gridView.cellHeight
|
height: gridView.cellHeight
|
||||||
text: device.name.toUpperCase()
|
device: engine.deviceManager.devices.getDevice(deviceId)
|
||||||
iconName: app.interfacesToIcon(deviceClass.interfaces)
|
|
||||||
iconColor: app.accentColor
|
|
||||||
visible: !fakeDragItem.visible || fakeDragItem.deviceId !== device.id
|
|
||||||
batteryCritical: batteryCriticalState && batteryCriticalState.value === true
|
|
||||||
disconnected: connectedState && connectedState.value === false
|
|
||||||
|
|
||||||
property var modelIndex: index
|
|
||||||
|
|
||||||
property string deviceId: model.deviceId
|
|
||||||
property string ruleId: model.ruleId
|
|
||||||
readonly property Device device: engine.deviceManager.devices.getDevice(deviceId)
|
|
||||||
readonly property DeviceClass deviceClass: device ? engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) : null
|
|
||||||
readonly property State connectedState: deviceClass.interfaces.indexOf("connectable") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("connected").id) : null
|
|
||||||
readonly property State batteryCriticalState: deviceClass.interfaces.indexOf("battery") >= 0 ? device.states.getState(deviceClass.stateTypes.findByName("batteryCritical").id) : null
|
|
||||||
|
|
||||||
onClicked: pageStack.push(Qt.resolvedUrl("../devicepages/" + app.interfaceListToDevicePage(deviceClass.interfaces)), {device: device})
|
onClicked: pageStack.push(Qt.resolvedUrl("../devicepages/" + app.interfaceListToDevicePage(deviceClass.interfaces)), {device: device})
|
||||||
|
|
||||||
onPressAndHold: root.editMode = true
|
onPressAndHold: root.editMode = true
|
||||||
|
|
||||||
contentItem: Loader {
|
|
||||||
id: loader
|
|
||||||
anchors.fill: parent
|
|
||||||
sourceComponent: {
|
|
||||||
if (delegateRoot.deviceClass.interfaces.indexOf("closable") >= 0) {
|
|
||||||
return closableComponent;
|
|
||||||
}
|
|
||||||
if (delegateRoot.deviceClass.interfaces.indexOf("power") >= 0) {
|
|
||||||
return lightsComponent;
|
|
||||||
}
|
|
||||||
if (delegateRoot.deviceClass.interfaces.indexOf("sensor") >= 0) {
|
|
||||||
return sensorsComponent;
|
|
||||||
}
|
|
||||||
if (delegateRoot.deviceClass.interfaces.indexOf("weather") >= 0) {
|
|
||||||
return sensorsComponent;
|
|
||||||
}
|
|
||||||
if (delegateRoot.deviceClass.interfaces.indexOf("smartmeter") >= 0) {
|
|
||||||
return sensorsComponent;
|
|
||||||
}
|
|
||||||
if (delegateRoot.deviceClass.interfaces.indexOf("mediacontroller") >= 0) {
|
|
||||||
return mediaComponent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binding { target: loader.item ? loader.item : null; property: "deviceClass"; value: delegateRoot.deviceClass }
|
|
||||||
Binding { target: loader.item ? loader.item : null; property: "device"; value: delegateRoot.device }
|
|
||||||
}
|
|
||||||
|
|
||||||
SequentialAnimation {
|
SequentialAnimation {
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
running: root.editMode
|
running: root.editMode
|
||||||
@ -174,330 +138,4 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
|
||||||
id: lightsComponent
|
|
||||||
RowLayout {
|
|
||||||
property var device: null
|
|
||||||
property var deviceClass: null
|
|
||||||
|
|
||||||
readonly property var powerStateType: deviceClass.stateTypes.findByName("power");
|
|
||||||
readonly property var powerState: device.states.getState(powerStateType.id)
|
|
||||||
|
|
||||||
readonly property var brightnessStateType: deviceClass.stateTypes.findByName("brightness");
|
|
||||||
readonly property var brightnessState: brightnessStateType ? device.states.getState(brightnessStateType.id) : null
|
|
||||||
|
|
||||||
ThrottledSlider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.leftMargin: app.margins / 2
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
opacity: deviceClass.interfaces.indexOf("dimmablelight") >= 0 ? 1 : 0
|
|
||||||
enabled: opacity > 0
|
|
||||||
from: 0
|
|
||||||
to: 100
|
|
||||||
value: brightnessState ? brightnessState.value : 0
|
|
||||||
onMoved: {
|
|
||||||
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
|
||||||
var actionType = deviceClass.actionTypes.findByName("brightness");
|
|
||||||
var params = [];
|
|
||||||
var powerParam = {}
|
|
||||||
powerParam["paramTypeId"] = actionType.paramTypes.get(0).id;
|
|
||||||
powerParam["value"] = value;
|
|
||||||
params.push(powerParam)
|
|
||||||
engine.deviceManager.executeAction(device.id, actionType.id, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemDelegate {
|
|
||||||
Layout.preferredWidth: app.iconSize
|
|
||||||
Layout.preferredHeight: width
|
|
||||||
Layout.rightMargin: app.margins / 2
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
padding: 0; topPadding: 0; bottomPadding: 0
|
|
||||||
|
|
||||||
contentItem: ColorIcon {
|
|
||||||
name: deviceClass.interfaces.indexOf("light") >= 0
|
|
||||||
? (powerState.value === true ? "../images/light-on.svg" : "../images/light-off.svg")
|
|
||||||
: app.interfacesToIcon(deviceClass.interfaces)
|
|
||||||
color: powerState.value === true ? app.accentColor : keyColor
|
|
||||||
}
|
|
||||||
onClicked: {
|
|
||||||
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
|
||||||
var actionType = deviceClass.actionTypes.findByName("power");
|
|
||||||
var params = [];
|
|
||||||
var powerParam = {}
|
|
||||||
powerParam["paramTypeId"] = actionType.paramTypes.get(0).id;
|
|
||||||
powerParam["value"] = !powerState.value;
|
|
||||||
params.push(powerParam)
|
|
||||||
engine.deviceManager.executeAction(device.id, actionType.id, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: sensorsComponent
|
|
||||||
RowLayout {
|
|
||||||
id: sensorsRoot
|
|
||||||
property var device: null
|
|
||||||
property var deviceClass: null
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
property var shownInterfaces: []
|
|
||||||
property int currentStateIndex: -1
|
|
||||||
property var currentStateType: deviceClass ? deviceClass.stateTypes.findByName(shownInterfaces[currentStateIndex].state) : null
|
|
||||||
property var currentState: currentStateType ? device.states.getState(currentStateType.id) : null
|
|
||||||
|
|
||||||
onDeviceClassChanged: {
|
|
||||||
if (deviceClass == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tmp = []
|
|
||||||
if (deviceClass.interfaces.indexOf("temperaturesensor") >= 0) {
|
|
||||||
tmp.push({iface: "temperaturesensor", state: "temperature"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("humiditysensor") >= 0) {
|
|
||||||
tmp.push({iface: "humiditysensor", state: "humidity"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("moisturesensor") >= 0) {
|
|
||||||
tmp.push({iface: "moisturesensor", state: "moisture"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("pressuresensor") >= 0) {
|
|
||||||
tmp.push({iface: "pressuresensor", state: "pressure"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("lightsensor") >= 0) {
|
|
||||||
tmp.push({iface: "lightsensor", state: "lightIntensity"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("conductivitysensor") >= 0) {
|
|
||||||
tmp.push({iface: "conductivitysensor", state: "conductivity"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("noisesensor") >= 0) {
|
|
||||||
tmp.push({iface: "noisesensor", state: "noise"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("co2sensor") >= 0) {
|
|
||||||
tmp.push({iface: "co2sensor", state: "co2"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("smartmeterconsumer") >= 0) {
|
|
||||||
tmp.push({iface: "smartmeterconsumer", state: "totalEnergyConsumed"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("smartmeterproducer") >= 0) {
|
|
||||||
tmp.push({iface: "smartmeterproducer", state: "totalEnergyProduced"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("daylightsensor") >= 0) {
|
|
||||||
tmp.push({iface: "daylightsensor", state: "daylight"});
|
|
||||||
}
|
|
||||||
if (deviceClass.interfaces.indexOf("presencesensor") >= 0) {
|
|
||||||
tmp.push({iface: "presencesensor", state: "isPresent"});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deviceClass.interfaces.indexOf("weather") >= 0) {
|
|
||||||
tmp.push({iface: "temperaturesensor", state: "temperature"});
|
|
||||||
tmp.push({iface: "humiditysensor", state: "humidity"});
|
|
||||||
tmp.push({iface: "pressuresensor", state: "pressure"});
|
|
||||||
}
|
|
||||||
|
|
||||||
shownInterfaces = tmp
|
|
||||||
currentStateIndex = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemDelegate {
|
|
||||||
Layout.preferredWidth: app.iconSize
|
|
||||||
Layout.preferredHeight: width
|
|
||||||
Layout.leftMargin: app.margins / 2
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
padding: 0; topPadding: 0; bottomPadding: 0
|
|
||||||
visible: sensorsRoot.shownInterfaces.length > 1
|
|
||||||
contentItem: ColorIcon {
|
|
||||||
name: "../images/back.svg"
|
|
||||||
}
|
|
||||||
onClicked: {
|
|
||||||
var newIndex = sensorsRoot.currentStateIndex - 1;
|
|
||||||
if (newIndex < 0) newIndex = sensorsRoot.shownInterfaces.length - 1
|
|
||||||
sensorsRoot.currentStateIndex = newIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item { Layout.fillHeight: true; Layout.fillWidth: true }
|
|
||||||
ColorIcon {
|
|
||||||
Layout.preferredWidth: app.iconSize
|
|
||||||
Layout.preferredHeight: width
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
color: app.interfaceToColor(sensorsRoot.shownInterfaces[sensorsRoot.currentStateIndex].iface)
|
|
||||||
name: app.interfaceToIcon(sensorsRoot.shownInterfaces[sensorsRoot.currentStateIndex].iface)
|
|
||||||
}
|
|
||||||
|
|
||||||
Item { Layout.fillHeight: true; Layout.fillWidth: true }
|
|
||||||
ColumnLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: 0
|
|
||||||
visible: sensorsRoot.currentStateType.type.toLowerCase() !== "bool"
|
|
||||||
|
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
text: sensorsRoot.currentStateType.unitString
|
|
||||||
font.pixelSize: app.smallFont
|
|
||||||
}
|
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
text: sensorsRoot.currentState.value// + " " + sensorsRoot.currentStateType.unitString
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Led {
|
|
||||||
state: sensorsRoot.currentState.value === true ? "on" : "off"
|
|
||||||
visible: sensorsRoot.currentStateType.type.toLowerCase() === "bool"
|
|
||||||
}
|
|
||||||
|
|
||||||
Item { Layout.fillHeight: true; Layout.fillWidth: true }
|
|
||||||
|
|
||||||
ItemDelegate {
|
|
||||||
Layout.preferredWidth: app.iconSize
|
|
||||||
Layout.preferredHeight: width
|
|
||||||
Layout.rightMargin: app.margins / 2
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
padding: 0; topPadding: 0; bottomPadding: 0
|
|
||||||
visible: sensorsRoot.shownInterfaces.length > 1
|
|
||||||
contentItem: ColorIcon {
|
|
||||||
name: "../images/next.svg"
|
|
||||||
}
|
|
||||||
onClicked: {
|
|
||||||
var newIndex = sensorsRoot.currentStateIndex + 1;
|
|
||||||
if (newIndex >= sensorsRoot.shownInterfaces.length) newIndex = 0;
|
|
||||||
sensorsRoot.currentStateIndex = newIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: closableComponent
|
|
||||||
RowLayout {
|
|
||||||
property var device: null
|
|
||||||
property var deviceClass: null
|
|
||||||
|
|
||||||
ItemDelegate {
|
|
||||||
Layout.preferredWidth: app.iconSize
|
|
||||||
Layout.preferredHeight: width
|
|
||||||
Layout.leftMargin: app.margins / 2
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
padding: 0; topPadding: 0; bottomPadding: 0
|
|
||||||
contentItem: ColorIcon {
|
|
||||||
name: "../images/up.svg"
|
|
||||||
color: app.accentColor
|
|
||||||
}
|
|
||||||
onClicked: {
|
|
||||||
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
|
||||||
var actionType = deviceClass.actionTypes.findByName("open");
|
|
||||||
engine.deviceManager.executeAction(device.id, actionType.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Slider {
|
|
||||||
id: closableSlider
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
visible: deviceClass.interfaces.indexOf("extendedclosable") >= 0
|
|
||||||
readonly property var percentageStateType: deviceClass.stateTypes.findByName("percentage");
|
|
||||||
readonly property var percentateState: device.states.getState(percentageStateType.id)
|
|
||||||
from: 0
|
|
||||||
to: 100
|
|
||||||
value: percentateState.value
|
|
||||||
}
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
visible: !closableSlider.visible
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemDelegate {
|
|
||||||
Layout.preferredWidth: app.iconSize
|
|
||||||
Layout.preferredHeight: width
|
|
||||||
Layout.rightMargin: app.margins / 2
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
padding: 0; topPadding: 0; bottomPadding: 0
|
|
||||||
contentItem: ColorIcon {
|
|
||||||
name: "../images/down.svg"
|
|
||||||
color: app.accentColor
|
|
||||||
}
|
|
||||||
onClicked: {
|
|
||||||
var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
|
|
||||||
var actionType = deviceClass.actionTypes.findByName("close");
|
|
||||||
engine.deviceManager.executeAction(device.id, actionType.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: mediaComponent
|
|
||||||
RowLayout {
|
|
||||||
id: mediaRoot
|
|
||||||
|
|
||||||
property Device device: null
|
|
||||||
property DeviceClass deviceClass: null
|
|
||||||
|
|
||||||
readonly property State playbackState: device.states.getState(deviceClass.stateTypes.findByName("playbackStatus").id)
|
|
||||||
|
|
||||||
function executeAction(actionName, params) {
|
|
||||||
var actionTypeId = deviceClass.actionTypes.findByName(actionName).id;
|
|
||||||
engine.deviceManager.executeAction(device.id, actionTypeId, params)
|
|
||||||
}
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
|
|
||||||
ProgressButton {
|
|
||||||
Layout.preferredHeight: app.iconSize * .9
|
|
||||||
Layout.preferredWidth: height
|
|
||||||
imageSource: "../images/media-skip-backward.svg"
|
|
||||||
longpressImageSource: "../images/media-seek-backward.svg"
|
|
||||||
repeat: true
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
mediaRoot.executeAction("skipBack")
|
|
||||||
}
|
|
||||||
onLongpressed: {
|
|
||||||
mediaRoot.executeAction("fastRewind")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
|
|
||||||
ProgressButton {
|
|
||||||
Layout.preferredHeight: app.iconSize * 1.3
|
|
||||||
Layout.preferredWidth: height
|
|
||||||
imageSource: mediaRoot.playbackState.value === "Playing" ? "../images/media-playback-pause.svg" : "../images/media-playback-start.svg"
|
|
||||||
longpressImageSource: "../images/media-playback-stop.svg"
|
|
||||||
longpressEnabled: mediaRoot.playbackState.value !== "Stopped"
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (mediaRoot.playbackState.value === "Playing") {
|
|
||||||
mediaRoot.executeAction("pause")
|
|
||||||
} else {
|
|
||||||
mediaRoot.executeAction("play")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLongpressed: {
|
|
||||||
mediaRoot.executeAction("stop")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
ProgressButton {
|
|
||||||
Layout.preferredHeight: app.iconSize * .9
|
|
||||||
Layout.preferredWidth: height
|
|
||||||
imageSource: "../images/media-skip-forward.svg"
|
|
||||||
longpressImageSource: "../images/media-seek-forward.svg"
|
|
||||||
repeat: true
|
|
||||||
onClicked: {
|
|
||||||
mediaRoot.executeAction("skipNext")
|
|
||||||
}
|
|
||||||
onLongpressed: {
|
|
||||||
mediaRoot.executeAction("fastForward")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,10 @@ import Nymea 1.0
|
|||||||
import QtQuick.Controls.Material 2.2
|
import QtQuick.Controls.Material 2.2
|
||||||
import "../components"
|
import "../components"
|
||||||
|
|
||||||
Item {
|
MouseArea {
|
||||||
id: root
|
id: root
|
||||||
|
preventStealing: true
|
||||||
|
onWheel: wheel.accepted = true
|
||||||
|
|
||||||
readonly property int count: groupsGridView.count
|
readonly property int count: groupsGridView.count
|
||||||
|
|
||||||
@ -15,6 +17,7 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: app.margins / 2
|
anchors.margins: app.margins / 2
|
||||||
|
|
||||||
|
|
||||||
readonly property int minTileWidth: 180
|
readonly property int minTileWidth: 180
|
||||||
readonly property int minTileHeight: 180
|
readonly property int minTileHeight: 180
|
||||||
readonly property int tilesPerRow: root.width / minTileWidth
|
readonly property int tilesPerRow: root.width / minTileWidth
|
||||||
@ -48,7 +51,7 @@ Item {
|
|||||||
|
|
||||||
InterfacesProxy {
|
InterfacesProxy {
|
||||||
id: controlsInGroup
|
id: controlsInGroup
|
||||||
shownInterfaces: ["light", "simpleclosable"]
|
shownInterfaces: ["light", "simpleclosable", "mediacontroller"]
|
||||||
devicesProxyFilter: devicesInGroup
|
devicesProxyFilter: devicesInGroup
|
||||||
showStates: true
|
showStates: true
|
||||||
showActions: true
|
showActions: true
|
||||||
@ -61,7 +64,10 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentItem: ItemDelegate {
|
contentItem: ItemDelegate {
|
||||||
padding: 0
|
leftPadding: 0
|
||||||
|
topPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
bottomPadding: 0
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
pageStack.push(Qt.resolvedUrl("../grouping/GroupPage.qml"), {groupTag: model.tagId})
|
pageStack.push(Qt.resolvedUrl("../grouping/GroupPage.qml"), {groupTag: model.tagId})
|
||||||
@ -74,6 +80,7 @@ Item {
|
|||||||
color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .05)
|
color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .05)
|
||||||
Label {
|
Label {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
anchors { leftMargin: app.margins; rightMargin: app.margins }
|
anchors { leftMargin: app.margins; rightMargin: app.margins }
|
||||||
text: model.tagId.substring(6)
|
text: model.tagId.substring(6)
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
@ -82,22 +89,35 @@ Item {
|
|||||||
Item {
|
Item {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
ColorIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
height: app.iconSize * 2
|
||||||
|
width: height
|
||||||
|
visible: controlsInGroup.count == 0
|
||||||
|
color: app.accentColor
|
||||||
|
name: "../images/view-grid-symbolic.svg"
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: controlsInGroup
|
model: Math.min(controlsInGroup.count, parent.height / 50)
|
||||||
delegate: Loader {
|
delegate: Loader {
|
||||||
id: controlLoader
|
id: controlLoader
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.leftMargin: app.margins / 2
|
Layout.leftMargin: app.margins / 2
|
||||||
Layout.rightMargin: app.margins / 2
|
Layout.rightMargin: app.margins / 2
|
||||||
|
property string interfaceName: controlsInGroup.get(index).name
|
||||||
sourceComponent: {
|
sourceComponent: {
|
||||||
switch (model.name) {
|
switch (interfaceName) {
|
||||||
case "simpleclosable":
|
case "simpleclosable":
|
||||||
return closableDelegate
|
return closableDelegate
|
||||||
case "light":
|
case "light":
|
||||||
return lightDelegate
|
return lightDelegate
|
||||||
|
case "mediacontroller":
|
||||||
|
return mediaControllerDelegate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Binding {
|
Binding {
|
||||||
@ -111,74 +131,77 @@ Item {
|
|||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
}
|
||||||
Layout.fillWidth: true
|
Rectangle {
|
||||||
Layout.preferredHeight: app.iconSize * 1.2
|
Layout.fillWidth: true
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.preferredHeight: app.iconSize * 1.2
|
||||||
color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, 0.05)
|
color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, 0.05)
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: sensorsInGroup
|
model: sensorsInGroup
|
||||||
delegate: Row {
|
delegate: Row {
|
||||||
ColorIcon {
|
height: parent.height
|
||||||
height: app.iconSize * .8
|
|
||||||
width: height
|
ColorIcon {
|
||||||
name: app.interfaceToIcon(model.name)
|
height: app.iconSize * .8
|
||||||
color: app.interfaceToColor(model.name)
|
width: height
|
||||||
|
name: app.interfaceToIcon(model.name)
|
||||||
|
color: app.interfaceToColor(model.name)
|
||||||
|
}
|
||||||
|
DevicesProxy {
|
||||||
|
id: innerProxy
|
||||||
|
engine: _engine
|
||||||
|
parentProxy: devicesInGroup
|
||||||
|
shownInterfaces: [model.name]
|
||||||
|
}
|
||||||
|
|
||||||
|
Led {
|
||||||
|
visible: ["presencesensor"].indexOf(model.name) >= 0
|
||||||
|
state: {
|
||||||
|
var stateName = null
|
||||||
|
switch (model.name) {
|
||||||
|
case "presencesensor":
|
||||||
|
stateName = "isPresent"
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
DevicesProxy {
|
if (!stateName) {
|
||||||
id: innerProxy
|
return "off";
|
||||||
engine: _engine
|
}
|
||||||
parentProxy: devicesInGroup
|
var ret = false;
|
||||||
shownInterfaces: [model.name]
|
for (var i = 0; i < innerProxy.count; i++) {
|
||||||
|
ret |= innerProxy.get(i).states.getState(innerProxy.get(i).deviceClass.stateTypes.findByName(stateName).id).value
|
||||||
|
}
|
||||||
|
return ret ? "on" : "off";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
height: parent.height
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
text: {
|
||||||
|
var stateName = null;
|
||||||
|
switch (model.name) {
|
||||||
|
case "temperaturesensor":
|
||||||
|
stateName = "temperature";
|
||||||
|
break;
|
||||||
|
case "lightsensor":
|
||||||
|
stateName = "lightIntensity"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!stateName) {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
Led {
|
var ret = 0
|
||||||
visible: ["presencesensor"].indexOf(model.name) >= 0
|
for (var i = 0; i < innerProxy.count; i++) {
|
||||||
state: {
|
ret += innerProxy.get(i).states.getState(innerProxy.get(i).deviceClass.stateTypes.findByName(stateName).id).value
|
||||||
var stateName = null
|
|
||||||
switch (model.name) {
|
|
||||||
case "presencesensor":
|
|
||||||
stateName = "isPresent"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!stateName) {
|
|
||||||
return "off";
|
|
||||||
}
|
|
||||||
var ret = false;
|
|
||||||
for (var i = 0; i < innerProxy.count; i++) {
|
|
||||||
ret |= innerProxy.get(i).states.getState(innerProxy.get(i).deviceClass.stateTypes.findByName(stateName).id).value
|
|
||||||
}
|
|
||||||
return ret ? "on" : "off";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
text: {
|
|
||||||
var stateName = null;
|
|
||||||
switch (model.name) {
|
|
||||||
case "temperaturesensor":
|
|
||||||
stateName = "temperature";
|
|
||||||
break;
|
|
||||||
case "lightsensor":
|
|
||||||
stateName = "lightIntensity"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!stateName) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
var ret = 0
|
|
||||||
for (var i = 0; i < innerProxy.count; i++) {
|
|
||||||
ret += innerProxy.get(i).states.getState(innerProxy.get(i).deviceClass.stateTypes.findByName(stateName).id).value
|
|
||||||
}
|
|
||||||
return (ret / innerProxy.count).toFixed(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return (ret / innerProxy.count).toFixed(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,4 +374,19 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: mediaControllerDelegate
|
||||||
|
MediaControls {
|
||||||
|
property var devices: null
|
||||||
|
DevicesProxy {
|
||||||
|
id: mediaControllers
|
||||||
|
engine: _engine
|
||||||
|
parentProxy: devices
|
||||||
|
shownInterfaces: ["mediacontroller"]
|
||||||
|
}
|
||||||
|
|
||||||
|
device: mediaControllers.parentProxy ? mediaControllers.get(0) : null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,11 +5,15 @@ import Nymea 1.0
|
|||||||
import QtQuick.Controls.Material 2.2
|
import QtQuick.Controls.Material 2.2
|
||||||
import "../components"
|
import "../components"
|
||||||
|
|
||||||
Item {
|
MouseArea {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property int count: interfacesGridView.count
|
readonly property int count: interfacesGridView.count
|
||||||
|
|
||||||
|
// Prevent scroll events to swipe left/right in case they fall through the grid
|
||||||
|
preventStealing: true
|
||||||
|
onWheel: wheel.accepted = true
|
||||||
|
|
||||||
GridView {
|
GridView {
|
||||||
id: interfacesGridView
|
id: interfacesGridView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|||||||
Reference in New Issue
Block a user