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();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
@ -85,6 +85,12 @@ void DashboardModel::addWebViewItem(const QUrl &url, int columnSpan, int rowSpan
|
||||
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)
|
||||
{
|
||||
qWarning() << "removing" << index;
|
||||
@ -119,6 +125,7 @@ void DashboardModel::loadFromJson(const QByteArray &json)
|
||||
m_list.clear();
|
||||
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(json);
|
||||
qCritical() << "dashboard:" << qUtf8Printable(jsonDoc.toJson());
|
||||
foreach (const QVariant &itemVariant, jsonDoc.toVariant().toList()) {
|
||||
QVariantMap itemMap = itemVariant.toMap();
|
||||
QString type = itemMap.value("type").toString();
|
||||
@ -136,6 +143,8 @@ void DashboardModel::loadFromJson(const QByteArray &json)
|
||||
item = new DashboardSceneItem(itemMap.value("ruleId").toUuid(), this);
|
||||
} else if (type == "webview") {
|
||||
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 {
|
||||
qWarning() << "Dashboard item type" << type << "is not implemented. Skipping...";
|
||||
continue;
|
||||
@ -179,6 +188,10 @@ QByteArray DashboardModel::toJson() const
|
||||
if (webViewItem->interactive()) {
|
||||
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 {
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Type " + item->type().toUtf8() + " not implemented!");
|
||||
continue;
|
||||
|
||||
@ -30,6 +30,7 @@ public:
|
||||
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 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 move(int from, int to);
|
||||
|
||||
@ -182,6 +182,7 @@ int main(int argc, char *argv[])
|
||||
qmlRegisterUncreatableType<DashboardGraphItem>("Nymea", 1, 0, "DashboardGraphItem", "");
|
||||
qmlRegisterUncreatableType<DashboardSceneItem>("Nymea", 1, 0, "DashboardSceneItem", "");
|
||||
qmlRegisterUncreatableType<DashboardWebViewItem>("Nymea", 1, 0, "DashboardWebViewItem", "");
|
||||
qmlRegisterUncreatableType<DashboardStateItem>("Nymea", 1, 0, "DashboardStateItem", "");
|
||||
|
||||
qmlRegisterSingletonType<PrivacyPolicyHelper>("NymeaApp.Utils", 1, 0, "PrivacyPolicyHelper", PrivacyPolicyHelper::qmlProvider);
|
||||
qmlRegisterType<QHashQml>("NymeaApp.Utils", 1, 0, "QHash");
|
||||
|
||||
@ -314,5 +314,6 @@
|
||||
<file>ui/devicepages/NotificationsThingPage.qml</file>
|
||||
<file>ui/devicepages/ActionLogPage.qml</file>
|
||||
<file>ui/devicepages/EventLogPage.qml</file>
|
||||
<file>ui/mainviews/dashboard/DashboardStateDelegate.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -154,7 +154,7 @@ Item {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
text: root.text.toUpperCase()
|
||||
font.pixelSize: app.smallFont
|
||||
font.pixelSize: Style.smallFont.pixelSize
|
||||
font.letterSpacing: 1
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
@ -63,7 +63,8 @@ MainViewBase {
|
||||
"folder": "DashboardFolderDelegate.qml",
|
||||
"graph": "DashboardGraphDelegate.qml",
|
||||
"scene": "DashboardSceneDelegate.qml",
|
||||
"webview": "DashboardWebViewDelegate.qml"
|
||||
"webview": "DashboardWebViewDelegate.qml",
|
||||
"state": "DashboardStateDelegate.qml"
|
||||
}
|
||||
|
||||
onEditModeChanged: {
|
||||
|
||||
@ -75,6 +75,14 @@ NymeaDialog {
|
||||
internalPageStack.push(addFolderComponent)
|
||||
}
|
||||
}
|
||||
NymeaItemDelegate {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("State")
|
||||
iconName: "state"
|
||||
onClicked: {
|
||||
internalPageStack.push(addStateSelectThingComponent)
|
||||
}
|
||||
}
|
||||
NymeaItemDelegate {
|
||||
Layout.fillWidth: true
|
||||
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 {
|
||||
id: addGraphSelectStateComponent
|
||||
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 {
|
||||
id: addSceneComponent
|
||||
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