Add a state delegate to dashboard
This commit is contained in:
parent
557c47fe49
commit
595749e9d3
@ -163,3 +163,20 @@ void DashboardWebViewItem::setInteractive(bool interactive)
|
|||||||
emit changed();
|
emit changed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DashboardStateItem::DashboardStateItem(const QUuid &thingId, const QUuid &stateTypeId, QObject *parent):
|
||||||
|
DashboardItem("state", parent),
|
||||||
|
m_thingId(thingId),
|
||||||
|
m_stateTypeId(stateTypeId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid DashboardStateItem::thingId() const
|
||||||
|
{
|
||||||
|
return m_thingId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid DashboardStateItem::stateTypeId() const
|
||||||
|
{
|
||||||
|
return m_stateTypeId;
|
||||||
|
}
|
||||||
|
|||||||
@ -110,4 +110,18 @@ private:
|
|||||||
bool m_interactive = false;
|
bool m_interactive = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DashboardStateItem: public DashboardItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QUuid thingId READ thingId CONSTANT)
|
||||||
|
Q_PROPERTY(QUuid stateTypeId READ stateTypeId CONSTANT)
|
||||||
|
public:
|
||||||
|
explicit DashboardStateItem(const QUuid &thingId, const QUuid &stateTypeId, QObject *parent = nullptr);
|
||||||
|
QUuid thingId() const;
|
||||||
|
QUuid stateTypeId() const;
|
||||||
|
private:
|
||||||
|
QUuid m_thingId;
|
||||||
|
QUuid m_stateTypeId;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // DASHBOARDITEM_H
|
#endif // DASHBOARDITEM_H
|
||||||
|
|||||||
@ -85,6 +85,12 @@ void DashboardModel::addWebViewItem(const QUrl &url, int columnSpan, int rowSpan
|
|||||||
addItem(item, index);
|
addItem(item, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DashboardModel::addStateItem(const QUuid &thingId, const QUuid &stateTypeId, int index)
|
||||||
|
{
|
||||||
|
DashboardStateItem *item = new DashboardStateItem(thingId, stateTypeId, this);
|
||||||
|
addItem(item, index);
|
||||||
|
}
|
||||||
|
|
||||||
void DashboardModel::removeItem(int index)
|
void DashboardModel::removeItem(int index)
|
||||||
{
|
{
|
||||||
qWarning() << "removing" << index;
|
qWarning() << "removing" << index;
|
||||||
@ -119,6 +125,7 @@ void DashboardModel::loadFromJson(const QByteArray &json)
|
|||||||
m_list.clear();
|
m_list.clear();
|
||||||
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(json);
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(json);
|
||||||
|
qCritical() << "dashboard:" << qUtf8Printable(jsonDoc.toJson());
|
||||||
foreach (const QVariant &itemVariant, jsonDoc.toVariant().toList()) {
|
foreach (const QVariant &itemVariant, jsonDoc.toVariant().toList()) {
|
||||||
QVariantMap itemMap = itemVariant.toMap();
|
QVariantMap itemMap = itemVariant.toMap();
|
||||||
QString type = itemMap.value("type").toString();
|
QString type = itemMap.value("type").toString();
|
||||||
@ -136,6 +143,8 @@ void DashboardModel::loadFromJson(const QByteArray &json)
|
|||||||
item = new DashboardSceneItem(itemMap.value("ruleId").toUuid(), this);
|
item = new DashboardSceneItem(itemMap.value("ruleId").toUuid(), this);
|
||||||
} else if (type == "webview") {
|
} else if (type == "webview") {
|
||||||
item = new DashboardWebViewItem(itemMap.value("url").toUrl(), itemMap.value("interactive", false).toBool(), this);
|
item = new DashboardWebViewItem(itemMap.value("url").toUrl(), itemMap.value("interactive", false).toBool(), this);
|
||||||
|
} else if (type == "state") {
|
||||||
|
item = new DashboardStateItem(itemMap.value("thingId").toUuid(), itemMap.value("stateTypeId").toUuid(), this);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Dashboard item type" << type << "is not implemented. Skipping...";
|
qWarning() << "Dashboard item type" << type << "is not implemented. Skipping...";
|
||||||
continue;
|
continue;
|
||||||
@ -179,6 +188,10 @@ QByteArray DashboardModel::toJson() const
|
|||||||
if (webViewItem->interactive()) {
|
if (webViewItem->interactive()) {
|
||||||
map.insert("interactive", true);
|
map.insert("interactive", true);
|
||||||
}
|
}
|
||||||
|
} else if (item->type() == "state") {
|
||||||
|
DashboardStateItem *stateItem = dynamic_cast<DashboardStateItem*>(item);
|
||||||
|
map.insert("thingId", stateItem->thingId());
|
||||||
|
map.insert("stateTypeId", stateItem->stateTypeId());
|
||||||
} else {
|
} else {
|
||||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Type " + item->type().toUtf8() + " not implemented!");
|
Q_ASSERT_X(false, Q_FUNC_INFO, "Type " + item->type().toUtf8() + " not implemented!");
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -30,6 +30,7 @@ public:
|
|||||||
Q_INVOKABLE void addGraphItem(const QUuid &thingId, const QUuid &stateTypeId, int index = -1);
|
Q_INVOKABLE void addGraphItem(const QUuid &thingId, const QUuid &stateTypeId, int index = -1);
|
||||||
Q_INVOKABLE void addSceneItem(const QUuid &ruleId, int index = -1);
|
Q_INVOKABLE void addSceneItem(const QUuid &ruleId, int index = -1);
|
||||||
Q_INVOKABLE void addWebViewItem(const QUrl &url, int columnSpan, int rowSpan, bool interactive, int index = -1);
|
Q_INVOKABLE void addWebViewItem(const QUrl &url, int columnSpan, int rowSpan, bool interactive, int index = -1);
|
||||||
|
Q_INVOKABLE void addStateItem(const QUuid &thingId, const QUuid &stateTypeId, int index = -1);
|
||||||
|
|
||||||
Q_INVOKABLE void removeItem(int index);
|
Q_INVOKABLE void removeItem(int index);
|
||||||
Q_INVOKABLE void move(int from, int to);
|
Q_INVOKABLE void move(int from, int to);
|
||||||
|
|||||||
@ -182,6 +182,7 @@ int main(int argc, char *argv[])
|
|||||||
qmlRegisterUncreatableType<DashboardGraphItem>("Nymea", 1, 0, "DashboardGraphItem", "");
|
qmlRegisterUncreatableType<DashboardGraphItem>("Nymea", 1, 0, "DashboardGraphItem", "");
|
||||||
qmlRegisterUncreatableType<DashboardSceneItem>("Nymea", 1, 0, "DashboardSceneItem", "");
|
qmlRegisterUncreatableType<DashboardSceneItem>("Nymea", 1, 0, "DashboardSceneItem", "");
|
||||||
qmlRegisterUncreatableType<DashboardWebViewItem>("Nymea", 1, 0, "DashboardWebViewItem", "");
|
qmlRegisterUncreatableType<DashboardWebViewItem>("Nymea", 1, 0, "DashboardWebViewItem", "");
|
||||||
|
qmlRegisterUncreatableType<DashboardStateItem>("Nymea", 1, 0, "DashboardStateItem", "");
|
||||||
|
|
||||||
qmlRegisterSingletonType<PrivacyPolicyHelper>("NymeaApp.Utils", 1, 0, "PrivacyPolicyHelper", PrivacyPolicyHelper::qmlProvider);
|
qmlRegisterSingletonType<PrivacyPolicyHelper>("NymeaApp.Utils", 1, 0, "PrivacyPolicyHelper", PrivacyPolicyHelper::qmlProvider);
|
||||||
qmlRegisterType<QHashQml>("NymeaApp.Utils", 1, 0, "QHash");
|
qmlRegisterType<QHashQml>("NymeaApp.Utils", 1, 0, "QHash");
|
||||||
|
|||||||
@ -314,5 +314,6 @@
|
|||||||
<file>ui/devicepages/NotificationsThingPage.qml</file>
|
<file>ui/devicepages/NotificationsThingPage.qml</file>
|
||||||
<file>ui/devicepages/ActionLogPage.qml</file>
|
<file>ui/devicepages/ActionLogPage.qml</file>
|
||||||
<file>ui/devicepages/EventLogPage.qml</file>
|
<file>ui/devicepages/EventLogPage.qml</file>
|
||||||
|
<file>ui/mainviews/dashboard/DashboardStateDelegate.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -154,7 +154,7 @@ Item {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
width: parent.width
|
width: parent.width
|
||||||
text: root.text.toUpperCase()
|
text: root.text.toUpperCase()
|
||||||
font.pixelSize: app.smallFont
|
font.pixelSize: Style.smallFont.pixelSize
|
||||||
font.letterSpacing: 1
|
font.letterSpacing: 1
|
||||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
|||||||
@ -63,7 +63,8 @@ MainViewBase {
|
|||||||
"folder": "DashboardFolderDelegate.qml",
|
"folder": "DashboardFolderDelegate.qml",
|
||||||
"graph": "DashboardGraphDelegate.qml",
|
"graph": "DashboardGraphDelegate.qml",
|
||||||
"scene": "DashboardSceneDelegate.qml",
|
"scene": "DashboardSceneDelegate.qml",
|
||||||
"webview": "DashboardWebViewDelegate.qml"
|
"webview": "DashboardWebViewDelegate.qml",
|
||||||
|
"state": "DashboardStateDelegate.qml"
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditModeChanged: {
|
onEditModeChanged: {
|
||||||
|
|||||||
@ -75,6 +75,14 @@ NymeaDialog {
|
|||||||
internalPageStack.push(addFolderComponent)
|
internalPageStack.push(addFolderComponent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
NymeaItemDelegate {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("State")
|
||||||
|
iconName: "state"
|
||||||
|
onClicked: {
|
||||||
|
internalPageStack.push(addStateSelectThingComponent)
|
||||||
|
}
|
||||||
|
}
|
||||||
NymeaItemDelegate {
|
NymeaItemDelegate {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("Chart")
|
text: qsTr("Chart")
|
||||||
@ -234,8 +242,47 @@ NymeaDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: addStateSelectThingComponent
|
||||||
|
ColumnLayout {
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: Style.margins
|
||||||
|
Layout.rightMargin: Style.margins
|
||||||
|
ColorIcon {
|
||||||
|
name: "/ui/images/find.svg"
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: filterTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.preferredHeight: Style.delegateHeight * 6
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
ScrollBar.vertical: ScrollBar {}
|
||||||
|
|
||||||
|
model: ThingsProxy {
|
||||||
|
id: thingsProxy
|
||||||
|
engine: _engine
|
||||||
|
nameFilter: filterTextField.displayText
|
||||||
|
}
|
||||||
|
delegate: NymeaItemDelegate {
|
||||||
|
text: model.name
|
||||||
|
width: parent ? parent.width : 0 // silence warning on delegate descruction
|
||||||
|
iconName: app.interfacesToIcon(thingsProxy.get(index).thingClass.interfaces)
|
||||||
|
onClicked: {
|
||||||
|
internalPageStack.push(addStateSelectStateComponent, {thing: thingsProxy.get(index)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: addGraphSelectStateComponent
|
id: addGraphSelectStateComponent
|
||||||
ListView {
|
ListView {
|
||||||
@ -258,6 +305,28 @@ NymeaDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: addStateSelectStateComponent
|
||||||
|
ListView {
|
||||||
|
implicitHeight: Style.delegateHeight * 6
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
ScrollBar.vertical: ScrollBar {}
|
||||||
|
|
||||||
|
property Thing thing: null
|
||||||
|
model: thing.thingClass.stateTypes
|
||||||
|
width: parent.width
|
||||||
|
delegate: NymeaItemDelegate {
|
||||||
|
width: parent.width
|
||||||
|
text: model.displayName
|
||||||
|
onClicked: {
|
||||||
|
root.dashboardModel.addStateItem(thing.id, model.id, root.index)
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: addSceneComponent
|
id: addSceneComponent
|
||||||
ListView {
|
ListView {
|
||||||
|
|||||||
125
nymea-app/ui/mainviews/dashboard/DashboardStateDelegate.qml
Normal file
125
nymea-app/ui/mainviews/dashboard/DashboardStateDelegate.qml
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2020, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
import QtQuick 2.8
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Controls.Material 2.1
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtCharts 2.2
|
||||||
|
import Nymea 1.0
|
||||||
|
import NymeaApp.Utils 1.0
|
||||||
|
import "../../components"
|
||||||
|
import "../../delegates"
|
||||||
|
|
||||||
|
DashboardDelegateBase {
|
||||||
|
id: root
|
||||||
|
property DashboardStateItem item: null
|
||||||
|
|
||||||
|
readonly property Thing thing: engine.thingManager.fetchingData ? null : engine.thingManager.things.getThing(root.item.thingId)
|
||||||
|
readonly property StateType stateType: thing ? thing.thingClass.stateTypes.getStateType(item.stateTypeId) : null
|
||||||
|
readonly property State state: thing ? thing.state(root.item.stateTypeId) : null
|
||||||
|
|
||||||
|
contentItem: MainPageTile {
|
||||||
|
id: delegateRoot
|
||||||
|
height: root.height
|
||||||
|
width: root.width
|
||||||
|
// lowerText: root.thing.name + "\n" + root.stateType.displayName
|
||||||
|
// iconName: NymeaUtils.namedIcon(root.item.icon)
|
||||||
|
iconColor: Style.accentColor
|
||||||
|
// onClicked: pageStack.push(Qt.resolvedUrl("DashboardPage.qml"), {item: root.item})
|
||||||
|
onPressAndHold: root.longPressed();
|
||||||
|
contentItem: Item {
|
||||||
|
id: bottomLayout
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Style.smallMargins
|
||||||
|
|
||||||
|
ColorIcon {
|
||||||
|
size: Style.iconSize
|
||||||
|
name: root.thing ? app.interfacesToIcon(root.thing.thingClass.interfaces) : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.thing ? root.thing.name : ""
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
maximumLineCount: 2
|
||||||
|
font: Style.smallFont
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
width: parent.width
|
||||||
|
anchors.centerIn: parent
|
||||||
|
anchors.verticalCenterOffset: -bottomLayout.height / 2
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: root.stateType && root.stateType.type.toLowerCase() != "bool"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font: Style.largeFont
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: root.state ?
|
||||||
|
1.0 * Math.round(Types.toUiValue(root.state.value, root.stateType.unit) * Math.pow(10, 1)) / Math.pow(10, 1) + " " + Types.toUiUnit(root.stateType.unit)
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Led {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.preferredWidth: Style.bigIconSize
|
||||||
|
Layout.preferredHeight: Style.bigIconSize
|
||||||
|
anchors.verticalCenterOffset: -bottomLayout.height / 2
|
||||||
|
visible: root.stateType && root.stateType.type.toLowerCase() === "bool"
|
||||||
|
state: root.state && root.state.value === true ? "on" : "off"
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: root.stateType ? root.stateType.displayName.toUpperCase() : ""
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
font.pixelSize: Style.smallFont.pixelSize
|
||||||
|
font.letterSpacing: 1
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
maximumLineCount: 2
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user