More improvements in the thing lists
This commit is contained in:
parent
592e1021b6
commit
aaa50ccdff
@ -235,5 +235,6 @@
|
||||
<file>ui/components/ColorPicker.qml</file>
|
||||
<file>ui/utils/ActionQueue.qml</file>
|
||||
<file>ui/components/ColorTemperaturePicker.qml</file>
|
||||
<file>ui/components/ThingContextMenu.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -32,6 +32,7 @@ import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
Menu {
|
||||
modal: true
|
||||
function calculateWidth() {
|
||||
var result = 0;
|
||||
var i = 0;
|
||||
|
||||
@ -3,7 +3,7 @@ import QtQuick.Layouts 1.2
|
||||
import QtQuick.Controls 2.1
|
||||
import Nymea 1.0
|
||||
|
||||
Item {
|
||||
Item {
|
||||
id: root
|
||||
implicitHeight: layout.implicitHeight + app.margins
|
||||
|
||||
@ -18,6 +18,10 @@ Item {
|
||||
property alias topPadding: content.topPadding
|
||||
property alias bottomPadding: content.bottomPadding
|
||||
|
||||
readonly property State connectedState: thing.stateByName("connected")
|
||||
readonly property bool isConnected: connectedState === null || connectedState.value === true
|
||||
readonly property bool isEnabled: thing.setupStatus == Thing.ThingSetupStatusComplete && isConnected
|
||||
|
||||
signal clicked();
|
||||
signal pressAndHold();
|
||||
|
||||
@ -25,6 +29,13 @@ Item {
|
||||
wobbleAnimation.start();
|
||||
}
|
||||
|
||||
onPressAndHold: {
|
||||
var contextMenuComponent = Qt.createComponent("../components/ThingContextMenu.qml");
|
||||
var contextMenu = contextMenuComponent.createObject(root, { thing: root.thing })
|
||||
contextMenu.x = Qt.binding(function() { return (root.width - contextMenu.width) / 2 })
|
||||
contextMenu.open()
|
||||
}
|
||||
|
||||
transform: Translate { id: wobbleTransform }
|
||||
|
||||
SequentialAnimation {
|
||||
|
||||
164
nymea-app/ui/components/ThingContextMenu.qml
Normal file
164
nymea-app/ui/components/ThingContextMenu.qml
Normal file
@ -0,0 +1,164 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Layouts 1.1
|
||||
import Nymea 1.0
|
||||
|
||||
AutoSizeMenu {
|
||||
id: root
|
||||
|
||||
property Thing thing: null
|
||||
|
||||
property bool showDetails: true
|
||||
property bool showLogs: true
|
||||
|
||||
Component.onCompleted: {
|
||||
root.addItem(menuEntryComponent.createObject(root, {text: qsTr("Magic"), iconSource: "../images/magic.svg", functionName: "openThingMagicPage"}))
|
||||
|
||||
if (root.showDetails) {
|
||||
root.addItem(menuEntryComponent.createObject(root, {text: qsTr("Details"), iconSource: "../images/info.svg", functionName: "openGenericThingPage"}))
|
||||
}
|
||||
// root.addItem(menuEntryComponent.createObject(root, {text: qsTr("Settings"), iconSource: "../images/configure.svg", functionName: "openThingSettingsPage"}))
|
||||
if (root.showLogs) {
|
||||
root.addItem(menuEntryComponent.createObject(root, {text: qsTr("Logs"), iconSource: "../images/logs.svg", functionName: "openThingLogPage"}))
|
||||
}
|
||||
|
||||
if (engine.jsonRpcClient.ensureServerVersion("1.6")) {
|
||||
root.addItem(menuEntryComponent.createObject(root,
|
||||
{
|
||||
text: Qt.binding(function() { return favoritesProxy.count === 0 ? qsTr("Mark as favorite") : qsTr("Remove from favorites")}),
|
||||
iconSource: Qt.binding(function() { return favoritesProxy.count === 0 ? "../images/starred.svg" : "../images/non-starred.svg"}),
|
||||
functionName: "toggleFavorite"
|
||||
}))
|
||||
|
||||
root.addItem(menuEntryComponent.createObject(root,
|
||||
{
|
||||
text: qsTr("Grouping"),
|
||||
iconSource: "../images/view-grid-symbolic.svg",
|
||||
functionName: "addToGroup"
|
||||
}))
|
||||
}
|
||||
|
||||
print("*** creating menu")
|
||||
print("NFC", NfcHelper.isAvailable)
|
||||
if (NfcHelper.isAvailable) {
|
||||
root.addItem(menuEntryComponent.createObject(root,
|
||||
{
|
||||
text: qsTr("Write NFC tag"),
|
||||
iconSource: "../images/nfc.svg",
|
||||
functionName: "writeNfcTag"
|
||||
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
function openThingMagicPage() {
|
||||
pageStack.push(Qt.resolvedUrl("../magic/DeviceRulesPage.qml"), {thing: root.thing})
|
||||
}
|
||||
function openGenericThingPage() {
|
||||
pageStack.push(Qt.resolvedUrl("../devicepages/GenericDevicePage.qml"), {thing: root.thing})
|
||||
}
|
||||
function toggleFavorite() {
|
||||
if (favoritesProxy.count === 0) {
|
||||
engine.tagsManager.tagDevice(root.thing.id, "favorites", 100000)
|
||||
} else {
|
||||
engine.tagsManager.untagDevice(root.thing.id, "favorites")
|
||||
}
|
||||
}
|
||||
function addToGroup() {
|
||||
var dialog = addToGroupDialog.createObject(root.parent)
|
||||
dialog.open();
|
||||
}
|
||||
|
||||
function openThingSettingsPage() {
|
||||
pageStack.push(Qt.resolvedUrl("../thingconfiguration/ConfigureThingPage.qml"), {thing: root.thing})
|
||||
}
|
||||
|
||||
function openThingLogPage() {
|
||||
pageStack.push(Qt.resolvedUrl("../devicepages/DeviceLogPage.qml"), {thing: root.thing });
|
||||
}
|
||||
|
||||
function writeNfcTag() {
|
||||
pageStack.push(Qt.resolvedUrl("../magic/WriteNfcTagPage.qml"), {thing: root.thing})
|
||||
}
|
||||
|
||||
TagsProxyModel {
|
||||
id: favoritesProxy
|
||||
tags: engine.tagsManager.tags
|
||||
filterDeviceId: root.thing.id
|
||||
filterTagId: "favorites"
|
||||
}
|
||||
|
||||
Component {
|
||||
id: menuEntryComponent
|
||||
IconMenuItem {
|
||||
width: parent.width
|
||||
property string functionName: ""
|
||||
onTriggered: root[functionName]()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: addToGroupDialog
|
||||
MeaDialog {
|
||||
title: qsTr("Groups for %1").arg(root.thing.name)
|
||||
headerIcon: "../images/view-grid-symbolic.svg"
|
||||
// NOTE: If CloseOnPressOutside is active (default) it will break the QtVirtualKeyboard
|
||||
// https://bugreports.qt.io/browse/QTBUG-56918
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
|
||||
RowLayout {
|
||||
Layout.leftMargin: app.margins
|
||||
Layout.rightMargin: app.margins
|
||||
spacing: app.margins
|
||||
TextField {
|
||||
id: newGroupdTextField
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr("New group")
|
||||
}
|
||||
Button {
|
||||
text: qsTr("OK")
|
||||
enabled: newGroupdTextField.displayText.length > 0 && !groupTags.containsId("group-" + newGroupdTextField.displayText)
|
||||
onClicked: {
|
||||
engine.tagsManager.tagDevice(root.thing.id, "group-" + newGroupdTextField.text, 1000)
|
||||
newGroupdTextField.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ListView {
|
||||
Layout.fillWidth: true
|
||||
height: 200
|
||||
clip: true
|
||||
ScrollIndicator.vertical: ScrollIndicator {}
|
||||
|
||||
model: TagListModel {
|
||||
id: groupTags
|
||||
tagsProxy: TagsProxyModel {
|
||||
tags: engine.tagsManager.tags
|
||||
filterTagId: "group-.*"
|
||||
}
|
||||
}
|
||||
|
||||
delegate: CheckDelegate {
|
||||
width: parent.width
|
||||
text: model.tagId.substring(6)
|
||||
checked: innerProxy.count > 0
|
||||
onClicked: {
|
||||
if (innerProxy.count == 0) {
|
||||
engine.tagsManager.tagDevice(root.thing.id, model.tagId, 1000)
|
||||
} else {
|
||||
engine.tagsManager.untagDevice(root.thing.id, model.tagId, model.value)
|
||||
}
|
||||
}
|
||||
ThingsProxy {
|
||||
id: innerProxy
|
||||
engine: _engine
|
||||
filterTagId: model.tagId
|
||||
filterDeviceId: root.thing.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,23 +1,60 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.1
|
||||
import QtQuick.Layouts 1.1
|
||||
import Nymea 1.0
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
Layout.fillWidth: false
|
||||
spacing: app.margins / 2
|
||||
|
||||
property Thing thing: null
|
||||
|
||||
property color color: keyColor
|
||||
readonly property color keyColor: updateStatusIcon.keyColor
|
||||
|
||||
signal updateIconClicked();
|
||||
signal batteryIconClicked();
|
||||
signal connectionIconClicked();
|
||||
signal setupIconClicked();
|
||||
|
||||
UpdateStatusIcon {
|
||||
id: updateStatusIcon
|
||||
Layout.preferredHeight: app.smallIconSize
|
||||
Layout.preferredWidth: height
|
||||
thing: root.thing
|
||||
visible: updateAvailable || updateRunning
|
||||
visible: setupStatusIcon.setupStatus == Thing.ThingSetupStatusComplete && connectionStatusIcon.isConnected && (updateAvailable || updateRunning)
|
||||
Binding { target: updateStatusIcon; property: "color"; value: root.color; when: root.color !== root.keyColor }
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -app.margins / 4
|
||||
onClicked: {
|
||||
var dialogComponent = Qt.createComponent("MeaDialog.qml")
|
||||
var currentVersionState = root.thing.stateByName("currentVersion")
|
||||
var availableVersionState = root.thing.stateByName("availableVersion")
|
||||
var text = qsTr("An update for %1 is available. Do you want to start the update now?").arg(root.thing.name)
|
||||
if (currentVersionState) {
|
||||
text += "\n\n" + qsTr("Current version: %1").arg(currentVersionState.value)
|
||||
}
|
||||
if (availableVersionState) {
|
||||
text += "\n\n" + qsTr("Available version: %1").arg(availableVersionState.value)
|
||||
}
|
||||
|
||||
var dialog = dialogComponent.createObject(app,
|
||||
{
|
||||
headerIcon: "../images/system-update.svg",
|
||||
title: qsTr("Update"),
|
||||
text: text,
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
})
|
||||
dialog.accepted.connect(function() {
|
||||
print("starting update")
|
||||
engine.thingManager.executeAction(root.thing.id, root.thing.thingClass.actionTypes.findByName("performUpdate").id)
|
||||
})
|
||||
dialog.open();
|
||||
root.updateIconClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
BatteryStatusIcon {
|
||||
id: batteryStatusIcon
|
||||
@ -26,6 +63,27 @@ RowLayout {
|
||||
thing: root.thing
|
||||
visible: root.thing.setupStatus == Thing.ThingSetupStatusComplete && (hasBatteryLevel || isCritical)
|
||||
Binding { target: batteryStatusIcon; property: "color"; value: root.color; when: root.color !== root.keyColor }
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -app.margins / 4
|
||||
onClicked: {
|
||||
root.batteryIconClicked()
|
||||
var levelStateType = root.thing.thingClass.stateTypes.findByName("batteryLevel");
|
||||
var criticalStateType = root.thing.thingClass.stateTypes.findByName("batteryCritical");
|
||||
var stateTypes = []
|
||||
if (levelStateType) {
|
||||
stateTypes.push(levelStateType.id)
|
||||
}
|
||||
if (criticalStateType) {
|
||||
stateTypes.push(criticalStateType.id)
|
||||
}
|
||||
pageStack.push("../devicepages/DeviceLogPage.qml",
|
||||
{
|
||||
thing: root.thing,
|
||||
filterTypeIds: stateTypes
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
ConnectionStatusIcon {
|
||||
id: connectionStatusIcon
|
||||
@ -34,6 +92,27 @@ RowLayout {
|
||||
thing: root.thing
|
||||
visible: root.thing.setupStatus == Thing.ThingSetupStatusComplete && (hasSignalStrength || !isConnected)
|
||||
Binding { target: connectionStatusIcon; property: "color"; value: root.color; when: root.color !== root.keyColor }
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -app.margins / 4
|
||||
onClicked: {
|
||||
root.connectionIconClicked()
|
||||
var signalStateType = root.thing.thingClass.stateTypes.findByName("signalStrength")
|
||||
var connectedStateType = root.thing.thingClass.stateTypes.findByName("connected")
|
||||
var stateTypes = []
|
||||
if (signalStateType) {
|
||||
stateTypes.push(signalStateType.id)
|
||||
}
|
||||
if (connectedStateType) {
|
||||
stateTypes.push(connectedStateType.id)
|
||||
}
|
||||
pageStack.push("../devicepages/DeviceLogPage.qml",
|
||||
{
|
||||
thing: root.thing,
|
||||
filterTypeIds: stateTypes
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
SetupStatusIcon {
|
||||
id: setupStatusIcon
|
||||
@ -42,5 +121,13 @@ RowLayout {
|
||||
thing: root.thing
|
||||
visible: setupFailed || setupInProgress
|
||||
Binding { target: setupStatusIcon; property: "color"; value: root.color; when: root.color !== root.keyColor }
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -app.margins / 4
|
||||
onClicked: {
|
||||
root.setupIconClicked()
|
||||
pageStack.push("../thingconfiguration/ConfigureThingPage.qml", { thing: root.thing });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,13 +103,17 @@ DeviceListPageBase {
|
||||
Layout.preferredWidth: contentGrid.width / contentGrid.columns
|
||||
thing: root.thingsProxy.getThing(model.id)
|
||||
showHeader: false
|
||||
enabled: connectedState == null || connectedState.value === true
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
onClicked: root.enterPage(index)
|
||||
onClicked: {
|
||||
if (isEnabled) {
|
||||
root.enterPage(index)
|
||||
} else {
|
||||
itemDelegate.wobble()
|
||||
}
|
||||
}
|
||||
|
||||
property State connectedState: thing.stateByName("connected")
|
||||
property State movingState: thing.stateByName("moving")
|
||||
property State percentageState: thing.stateByName("percentage")
|
||||
|
||||
@ -131,6 +135,7 @@ DeviceListPageBase {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.thing.name
|
||||
elide: Text.ElideRight
|
||||
enabled: itemDelegate.isEnabled
|
||||
}
|
||||
|
||||
ThingStatusIcons {
|
||||
@ -143,6 +148,7 @@ DeviceListPageBase {
|
||||
height: parent.height
|
||||
device: itemDelegate.thing
|
||||
invert: root.invertControls
|
||||
enabled: itemDelegate.isEnabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,13 +67,17 @@ DeviceListPageBase {
|
||||
Layout.preferredWidth: contentGrid.width / contentGrid.columns
|
||||
thing: root.thingsProxy.getThing(model.id)
|
||||
showHeader: false
|
||||
enabled: connectedState == null || connectedState.value === true
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
onClicked: root.enterPage(index)
|
||||
onClicked: {
|
||||
if (isEnabled) {
|
||||
root.enterPage(index)
|
||||
} else {
|
||||
itemDelegate.wobble()
|
||||
}
|
||||
}
|
||||
|
||||
property State connectedState: thing.stateByName("connected")
|
||||
property State movingState: thing.stateByName("moving")
|
||||
property State percentageState: thing.stateByName("percentage")
|
||||
|
||||
@ -97,6 +101,7 @@ DeviceListPageBase {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.thing.name
|
||||
elide: Text.ElideRight
|
||||
enabled: itemDelegate.isEnabled
|
||||
}
|
||||
|
||||
ThingStatusIcons {
|
||||
@ -110,6 +115,7 @@ DeviceListPageBase {
|
||||
device: itemDelegate.thing
|
||||
invert: root.invertControls
|
||||
visible: !itemDelegate.isImpulseBased
|
||||
enabled: itemDelegate.isEnabled
|
||||
}
|
||||
ProgressButton {
|
||||
Layout.preferredHeight: app.iconSize
|
||||
@ -117,6 +123,7 @@ DeviceListPageBase {
|
||||
longpressEnabled: false
|
||||
imageSource: "../images/closable-move.svg"
|
||||
visible: itemDelegate.isImpulseBased
|
||||
enabled: itemDelegate.isEnabled
|
||||
onClicked: {
|
||||
var actionTypeId = itemDelegate.thing.thingClass.actionTypes.findByName("triggerImpulse").id
|
||||
print("Triggering impulse", actionTypeId)
|
||||
|
||||
@ -73,11 +73,16 @@ DeviceListPageBase {
|
||||
Layout.preferredWidth: contentGrid.width / contentGrid.columns
|
||||
thing: root.thingsProxy.getThing(model.id)
|
||||
showHeader: false
|
||||
enabled: connectedState == null || connectedState.value === true
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
onClicked: root.enterPage(index)
|
||||
onClicked: {
|
||||
if (isEnabled) {
|
||||
root.enterPage(index)
|
||||
} else {
|
||||
itemDelegate.wobble()
|
||||
}
|
||||
}
|
||||
|
||||
property State connectedState: thing.stateByName("connected")
|
||||
property State powerState: thing.stateByName("power")
|
||||
@ -96,6 +101,7 @@ DeviceListPageBase {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.thing.name
|
||||
elide: Text.ElideRight
|
||||
enabled: itemDelegate.isEnabled
|
||||
}
|
||||
|
||||
ThingStatusIcons {
|
||||
@ -104,7 +110,8 @@ DeviceListPageBase {
|
||||
|
||||
Switch {
|
||||
visible: itemDelegate.powerState !== null
|
||||
checked: itemDelegate.powerState.value === true
|
||||
checked: itemDelegate.powerState && itemDelegate.powerState.value === true
|
||||
enabled: itemDelegate.isEnabled
|
||||
onClicked: {
|
||||
var params = [];
|
||||
var param1 = {};
|
||||
|
||||
@ -97,18 +97,16 @@ DeviceListPageBase {
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
|
||||
property State connectedState: thing.stateByName("connected")
|
||||
property State powerState: thing.stateByName("power")
|
||||
property State brightnessState: thing.stateByName("brightness")
|
||||
property State colorState: thing.stateByName("color")
|
||||
property State colorTemperatureState: thing.stateByName("colorTemperature")
|
||||
|
||||
property bool tileColored: isConnected && colorState && powerState.value === true
|
||||
property bool tileColored: isEnabled && colorState && powerState.value === true
|
||||
property bool colorInverted: tileColored && NymeaUtils.isDark(app.foregroundColor) === NymeaUtils.isDark(colorState.value)
|
||||
property bool isConnected: connectedState === null || connectedState.value === true
|
||||
|
||||
|
||||
onClicked: {
|
||||
if (isConnected) {
|
||||
if (isEnabled && (colorState || colorTemperatureState)) {
|
||||
root.enterPage(index)
|
||||
} else {
|
||||
itemDelegate.wobble()
|
||||
@ -126,7 +124,6 @@ DeviceListPageBase {
|
||||
implicitHeight: contentColumn.implicitHeight
|
||||
Behavior on implicitHeight { NumberAnimation { duration: 100 } }
|
||||
radius: 6
|
||||
enabled: itemDelegate.isConnected
|
||||
|
||||
ColumnLayout {
|
||||
id: contentColumn
|
||||
@ -156,6 +153,7 @@ DeviceListPageBase {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.thing.name
|
||||
elide: Text.ElideRight
|
||||
enabled: itemDelegate.isEnabled
|
||||
|
||||
Binding {
|
||||
target: nameLabel
|
||||
@ -172,6 +170,7 @@ DeviceListPageBase {
|
||||
Switch {
|
||||
id: lightSwitch
|
||||
checked: itemDelegate.powerState.value === true
|
||||
enabled: itemDelegate.isEnabled
|
||||
onClicked: {
|
||||
var params = [];
|
||||
var param1 = {};
|
||||
@ -256,6 +255,7 @@ DeviceListPageBase {
|
||||
visible: itemDelegate.powerState.value === true && itemDelegate.brightnessState != null
|
||||
radius: 6
|
||||
color: Qt.tint(app.backgroundColor, Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .1))
|
||||
enabled: itemDelegate.isEnabled
|
||||
|
||||
Rectangle {
|
||||
height: knob.x + knob.width / 2
|
||||
|
||||
@ -68,9 +68,6 @@ DeviceListPageBase {
|
||||
bottomPadding: 0
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
enabled: connectedState == null || connectedState.value === true
|
||||
|
||||
property State connectedState: thing.stateByName("connected")
|
||||
|
||||
readonly property StateType playbackStateType: thing.thingClass.stateTypes.findByName("playbackStatus")
|
||||
readonly property State playbackState: thing.stateByName("playbackStatus")
|
||||
@ -79,10 +76,15 @@ DeviceListPageBase {
|
||||
readonly property State playerTypeState: thing.stateByName("playerType")
|
||||
|
||||
onClicked: {
|
||||
enterPage(index)
|
||||
if (isEnabled) {
|
||||
enterPage(index)
|
||||
} else {
|
||||
itemDelegate.wobble();
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
enabled: itemDelegate.isEnabled
|
||||
ColumnLayout {
|
||||
id: leftColummn
|
||||
Layout.margins: app.margins
|
||||
@ -183,7 +185,6 @@ DeviceListPageBase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,11 +67,16 @@ DeviceListPageBase {
|
||||
Layout.preferredWidth: contentGrid.width / contentGrid.columns
|
||||
thing: root.thingsProxy.getThing(model.id)
|
||||
showHeader: false
|
||||
enabled: connectedState == null || connectedState.value === true
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
onClicked: root.enterPage(index)
|
||||
onClicked: {
|
||||
if (isEnabled) {
|
||||
root.enterPage(index)
|
||||
} else {
|
||||
itemDelegate.wobble();
|
||||
}
|
||||
}
|
||||
|
||||
property State connectedState: thing.stateByName("connected")
|
||||
property State powerState: thing.stateByName("power")
|
||||
@ -90,6 +95,7 @@ DeviceListPageBase {
|
||||
Layout.fillWidth: true
|
||||
text: itemDelegate.thing.name
|
||||
elide: Text.ElideRight
|
||||
enabled: itemDelegate.isEnabled
|
||||
}
|
||||
|
||||
ThingStatusIcons {
|
||||
@ -98,6 +104,7 @@ DeviceListPageBase {
|
||||
|
||||
Switch {
|
||||
checked: itemDelegate.powerState.value === true
|
||||
enabled: itemDelegate.isEnabled
|
||||
onClicked: {
|
||||
var params = [];
|
||||
var param1 = {};
|
||||
|
||||
@ -64,9 +64,7 @@ DeviceListPageBase {
|
||||
Layout.preferredWidth: contentGrid.width / contentGrid.columns
|
||||
thing: root.thingsProxy.getThing(model.id)
|
||||
|
||||
onClicked: {
|
||||
enterPage(index)
|
||||
}
|
||||
onClicked: enterPage(index)
|
||||
|
||||
contentItem: GridLayout {
|
||||
id: dataGrid
|
||||
|
||||
@ -39,11 +39,12 @@ import "../customviews"
|
||||
Page {
|
||||
id: root
|
||||
|
||||
property Device device: null
|
||||
property Thing thing: null
|
||||
property alias device: root.thing
|
||||
property var filterTypeIds: []
|
||||
|
||||
header: NymeaHeader {
|
||||
text: qsTr("History for %1").arg(root.device.name)
|
||||
text: qsTr("History for %1").arg(root.thing.name)
|
||||
onBackPressed: pageStack.pop()
|
||||
|
||||
HeaderButton {
|
||||
@ -57,7 +58,7 @@ Page {
|
||||
LogsModelNg {
|
||||
id: logsModelNg
|
||||
engine: _engine
|
||||
deviceId: root.device.id
|
||||
deviceId: root.thing.id
|
||||
typeIds: root.filterTypeIds.length > 0
|
||||
? root.filterTypeIds
|
||||
: filterEnabled
|
||||
@ -70,7 +71,7 @@ Page {
|
||||
|
||||
DeviceModel {
|
||||
id: filterDeviceModel
|
||||
device: root.device
|
||||
device: root.thing
|
||||
}
|
||||
|
||||
Pane {
|
||||
@ -111,7 +112,7 @@ Page {
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
readonly property StateType stateType: root.device.deviceClass.stateTypes.getStateType(root.filterTypeIds[0])
|
||||
readonly property StateType stateType: root.thing.thingClass.stateTypes.getStateType(root.filterTypeIds[0])
|
||||
|
||||
readonly property bool canShowGraph: {
|
||||
if (stateType === null) {
|
||||
@ -122,14 +123,15 @@ Page {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (stateType.type) {
|
||||
case "Int":
|
||||
case "Double":
|
||||
switch (stateType.type.toLowerCase()) {
|
||||
case "uint":
|
||||
case "int":
|
||||
case "double":
|
||||
return true;
|
||||
case "Bool":
|
||||
case "bool":
|
||||
return engine.jsonRpcClient.ensureServerVersion("1.10")
|
||||
}
|
||||
print("not showing graph for", root.stateType.type)
|
||||
print("not showing graph for", stateType.type)
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -142,7 +144,7 @@ Page {
|
||||
}
|
||||
|
||||
var source = Qt.resolvedUrl("../customviews/GenericTypeGraph.qml");
|
||||
setSource(source, {device: root.device, stateType: stateType})
|
||||
setSource(source, {device: root.thing, stateType: stateType})
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,9 +164,9 @@ Page {
|
||||
id: entryDelegate
|
||||
width: parent.width
|
||||
|
||||
property StateType stateType: model.source === LogEntry.LoggingSourceStates ? root.device.deviceClass.stateTypes.getStateType(model.typeId) : null
|
||||
property EventType eventType: model.source === LogEntry.LoggingSourceEvents || model.source === LogEntry.LoggingSourceStates ? root.device.deviceClass.eventTypes.getEventType(model.typeId) : null
|
||||
property ActionType actionType: model.source === LogEntry.LoggingSourceActions ? root.device.deviceClass.actionTypes.getActionType(model.typeId) : null
|
||||
property StateType stateType: model.source === LogEntry.LoggingSourceStates ? root.thing.thingClass.stateTypes.getStateType(model.typeId) : null
|
||||
property EventType eventType: model.source === LogEntry.LoggingSourceEvents || model.source === LogEntry.LoggingSourceStates ? root.thing.thingClass.eventTypes.getEventType(model.typeId) : null
|
||||
property ActionType actionType: model.source === LogEntry.LoggingSourceActions ? root.thing.thingClass.actionTypes.getActionType(model.typeId) : null
|
||||
|
||||
contentItem: RowLayout {
|
||||
ColorIcon {
|
||||
|
||||
@ -74,171 +74,21 @@ Page {
|
||||
}
|
||||
}
|
||||
|
||||
TagsProxyModel {
|
||||
id: favoritesProxy
|
||||
tags: engine.tagsManager.tags
|
||||
filterDeviceId: root.device.id
|
||||
filterTagId: "favorites"
|
||||
}
|
||||
|
||||
AutoSizeMenu {
|
||||
ThingContextMenu {
|
||||
id: thingMenu
|
||||
x: parent.width - width
|
||||
thing: root.thing
|
||||
showDetails: root.showDetailsButton
|
||||
showLogs: root.showLogsButton
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
thingMenu.addItem(menuEntryComponent.createObject(thingMenu, {text: qsTr("Magic"), iconSource: "../images/magic.svg", functionName: "openDeviceMagicPage"}))
|
||||
|
||||
if (root.showDetailsButton) {
|
||||
thingMenu.addItem(menuEntryComponent.createObject(thingMenu, {text: qsTr("Details"), iconSource: "../images/info.svg", functionName: "openGenericDevicePage"}))
|
||||
Connections {
|
||||
target: engine.deviceManager.devices
|
||||
onThingRemoved:{
|
||||
if (device == root.device) {
|
||||
print("Device destroyed")
|
||||
pageStack.pop()
|
||||
}
|
||||
// thingMenu.addItem(menuEntryComponent.createObject(thingMenu, {text: qsTr("Settings"), iconSource: "../images/configure.svg", functionName: "openThingSettingsPage"}))
|
||||
if (root.showLogsButton) {
|
||||
thingMenu.addItem(menuEntryComponent.createObject(thingMenu, {text: qsTr("Logs"), iconSource: "../images/logs.svg", functionName: "openDeviceLogPage"}))
|
||||
}
|
||||
|
||||
if (engine.jsonRpcClient.ensureServerVersion("1.6")) {
|
||||
thingMenu.addItem(menuEntryComponent.createObject(thingMenu,
|
||||
{
|
||||
text: Qt.binding(function() { return favoritesProxy.count === 0 ? qsTr("Mark as favorite") : qsTr("Remove from favorites")}),
|
||||
iconSource: Qt.binding(function() { return favoritesProxy.count === 0 ? "../images/starred.svg" : "../images/non-starred.svg"}),
|
||||
functionName: "toggleFavorite"
|
||||
}))
|
||||
|
||||
thingMenu.addItem(menuEntryComponent.createObject(thingMenu,
|
||||
{
|
||||
text: qsTr("Grouping"),
|
||||
iconSource: "../images/view-grid-symbolic.svg",
|
||||
functionName: "addToGroup"
|
||||
}))
|
||||
}
|
||||
|
||||
print("*** creating menu")
|
||||
print("NFC", NfcHelper.isAvailable)
|
||||
if (NfcHelper.isAvailable) {
|
||||
thingMenu.addItem(menuEntryComponent.createObject(thingMenu,
|
||||
{
|
||||
text: qsTr("Write NFC tag"),
|
||||
iconSource: "../images/nfc.svg",
|
||||
functionName: "writeNfcTag"
|
||||
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
function openDeviceMagicPage() {
|
||||
pageStack.push(Qt.resolvedUrl("../magic/DeviceRulesPage.qml"), {device: root.device})
|
||||
}
|
||||
function openGenericDevicePage() {
|
||||
pageStack.push(Qt.resolvedUrl("GenericDevicePage.qml"), {device: root.device})
|
||||
}
|
||||
function toggleFavorite() {
|
||||
if (favoritesProxy.count === 0) {
|
||||
engine.tagsManager.tagDevice(root.device.id, "favorites", 100000)
|
||||
} else {
|
||||
engine.tagsManager.untagDevice(root.device.id, "favorites")
|
||||
}
|
||||
}
|
||||
function addToGroup() {
|
||||
var dialog = addToGroupDialog.createObject(root)
|
||||
dialog.open();
|
||||
}
|
||||
|
||||
function openThingSettingsPage() {
|
||||
pageStack.push(Qt.resolvedUrl("../thingconfiguration/ConfigureThingPage.qml"), {device: root.device})
|
||||
}
|
||||
|
||||
function openDeviceLogPage() {
|
||||
pageStack.push(Qt.resolvedUrl("DeviceLogPage.qml"), {device: root.device });
|
||||
}
|
||||
|
||||
function writeNfcTag() {
|
||||
pageStack.push(Qt.resolvedUrl("../magic/WriteNfcTagPage.qml"), {thing: root.thing})
|
||||
}
|
||||
|
||||
Component {
|
||||
id: menuEntryComponent
|
||||
IconMenuItem {
|
||||
width: parent.width
|
||||
property string functionName: ""
|
||||
onTriggered: thingMenu[functionName]()
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: engine.deviceManager.devices
|
||||
onThingRemoved:{
|
||||
if (device == root.device) {
|
||||
print("Device destroyed")
|
||||
pageStack.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: addToGroupDialog
|
||||
MeaDialog {
|
||||
title: qsTr("Groups for %1").arg(root.device.name)
|
||||
headerIcon: "../images/view-grid-symbolic.svg"
|
||||
// NOTE: If CloseOnPressOutside is active (default) it will break the QtVirtualKeyboard
|
||||
// https://bugreports.qt.io/browse/QTBUG-56918
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
|
||||
RowLayout {
|
||||
Layout.leftMargin: app.margins
|
||||
Layout.rightMargin: app.margins
|
||||
spacing: app.margins
|
||||
TextField {
|
||||
id: newGroupdTextField
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr("New group")
|
||||
}
|
||||
Button {
|
||||
text: qsTr("OK")
|
||||
enabled: newGroupdTextField.displayText.length > 0 && !groupTags.containsId("group-" + newGroupdTextField.displayText)
|
||||
onClicked: {
|
||||
engine.tagsManager.tagDevice(root.device.id, "group-" + newGroupdTextField.text, 1000)
|
||||
newGroupdTextField.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ListView {
|
||||
Layout.fillWidth: true
|
||||
height: 200
|
||||
clip: true
|
||||
ScrollIndicator.vertical: ScrollIndicator {}
|
||||
|
||||
model: TagListModel {
|
||||
id: groupTags
|
||||
tagsProxy: TagsProxyModel {
|
||||
tags: engine.tagsManager.tags
|
||||
filterTagId: "group-.*"
|
||||
}
|
||||
}
|
||||
|
||||
delegate: CheckDelegate {
|
||||
width: parent.width
|
||||
text: model.tagId.substring(6)
|
||||
checked: innerProxy.count > 0
|
||||
onClicked: {
|
||||
if (innerProxy.count == 0) {
|
||||
engine.tagsManager.tagDevice(root.device.id, model.tagId, 1000)
|
||||
} else {
|
||||
engine.tagsManager.untagDevice(root.device.id, model.tagId, model.value)
|
||||
}
|
||||
}
|
||||
|
||||
DevicesProxy {
|
||||
id: innerProxy
|
||||
engine: _engine
|
||||
filterTagId: model.tagId
|
||||
filterDeviceId: root.device.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ DevicePageBase {
|
||||
|
||||
function executeAction(actionTypeId, params) {
|
||||
print("executing", actionTypeId)
|
||||
return engine.deviceManager.executeAction(root.device.id, actionTypeId, params)
|
||||
return engine.thingManager.executeAction(root.thing.id, actionTypeId, params)
|
||||
}
|
||||
|
||||
ListView {
|
||||
|
||||
@ -47,9 +47,9 @@ DevicePageBase {
|
||||
readonly property StateType movingStateType: isExtended ? deviceClass.stateTypes.findByName("moving") : null
|
||||
readonly property StateType angleStateType: isVenetian ? deviceClass.stateTypes.findByName("angle") : null
|
||||
|
||||
readonly property State movingState: isExtended ? device.states.getState(movingStateType.id) : 0
|
||||
readonly property State percentageState: isExtended ? device.states.getState(deviceClass.stateTypes.findByName("percentage").id) : 0
|
||||
readonly property State angleState: isVenetian ? device.states.getState(angleStateType.id) : 0
|
||||
readonly property State movingState: isExtended ? device.states.getState(movingStateType.id) : null
|
||||
readonly property State percentageState: isExtended ? device.states.getState(deviceClass.stateTypes.findByName("percentage").id) : null
|
||||
readonly property State angleState: isVenetian ? device.states.getState(angleStateType.id) : null
|
||||
|
||||
|
||||
readonly property bool moving: movingState ? movingState.value === true : false
|
||||
@ -212,8 +212,8 @@ DevicePageBase {
|
||||
id: angleMouseArea
|
||||
anchors.fill: parent
|
||||
// angle : totalAngle = mouseY : height
|
||||
property int totalAngle: root.angleStateType.maxValue - root.angleStateType.minValue
|
||||
property int angle: totalAngle * mouseY / height + root.angleStateType.minValue
|
||||
property int totalAngle: root.angleState ? root.angleStateType.maxValue - root.angleStateType.minValue : 0
|
||||
property int angle: root.angleState ? totalAngle * mouseY / height + root.angleStateType.minValue : 0
|
||||
hoverEnabled: true
|
||||
|
||||
property int startY: 0
|
||||
|
||||
@ -37,7 +37,8 @@ import Nymea 1.0
|
||||
Page {
|
||||
id: root
|
||||
|
||||
property var device: null
|
||||
property Thing thing: null
|
||||
property alias device: root.thing
|
||||
|
||||
Component.onCompleted: print("+++ created devicerulespage")
|
||||
Component.onDestruction: print("--- destroying devicerulespage")
|
||||
|
||||
Reference in New Issue
Block a user