Merge PR #1011: Improve new logging stuff further
commit
83a3cbcff1
|
|
@ -1,6 +1,7 @@
|
|||
#include "newlogsmodel.h"
|
||||
|
||||
#include "engine.h"
|
||||
#include "logmanager.h"
|
||||
|
||||
#include "logging.h"
|
||||
//NYMEA_LOGGING_CATEGORY(dcLogEngine, "LogEngine")
|
||||
|
|
@ -58,7 +59,8 @@ void NewLogsModel::componentComplete()
|
|||
bool NewLogsModel::canFetchMore(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_canFetchMore && m_sources.count() == 1;
|
||||
// Cannot fetchMore when there are multiple sources as paging doesn't really work in that case
|
||||
return m_canFetchMore && (m_sources.count() == 1 || m_list.isEmpty());
|
||||
}
|
||||
|
||||
void NewLogsModel::fetchMore(const QModelIndex &parent)
|
||||
|
|
@ -83,13 +85,19 @@ Engine *NewLogsModel::engine() const
|
|||
|
||||
void NewLogsModel::setEngine(Engine *engine)
|
||||
{
|
||||
if (m_engine != engine) {
|
||||
m_engine = engine;
|
||||
emit engineChanged();
|
||||
if (m_engine == engine) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if (m_completed && m_canFetchMore) {
|
||||
// fetchMore();
|
||||
// }
|
||||
if (m_engine) {
|
||||
disconnect(m_engine->logManager(), &LogManager::logEntryReceived, this, &NewLogsModel::newLogEntryReceived);
|
||||
}
|
||||
|
||||
m_engine = engine;
|
||||
emit engineChanged();
|
||||
|
||||
if (m_engine) {
|
||||
connect(m_engine->logManager(), &LogManager::logEntryReceived, this, &NewLogsModel::newLogEntryReceived);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,6 +211,32 @@ bool NewLogsModel::busy() const
|
|||
return m_busy;
|
||||
}
|
||||
|
||||
bool NewLogsModel::live() const
|
||||
{
|
||||
return m_live;
|
||||
}
|
||||
|
||||
void NewLogsModel::setLive(bool live)
|
||||
{
|
||||
if (m_live != live) {
|
||||
m_live = live;
|
||||
emit liveChanged();
|
||||
}
|
||||
}
|
||||
|
||||
int NewLogsModel::fetchBlockSize() const
|
||||
{
|
||||
return m_blockSize;
|
||||
}
|
||||
|
||||
void NewLogsModel::setFetchBlockSize(int fetchBlockSize)
|
||||
{
|
||||
if (m_blockSize != fetchBlockSize) {
|
||||
m_blockSize = fetchBlockSize;
|
||||
emit fetchBlockSizeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
NewLogEntry *NewLogsModel::get(int index) const
|
||||
{
|
||||
if (index < 0 || index >= m_list.count()) {
|
||||
|
|
@ -266,6 +300,8 @@ void NewLogsModel::clear()
|
|||
beginResetModel();
|
||||
qDeleteAll(m_list);
|
||||
m_list.clear();
|
||||
m_currentNewest = QDateTime();
|
||||
m_lastOffset = 0;
|
||||
endResetModel();
|
||||
emit countChanged();
|
||||
emit entriesRemoved(0, count);
|
||||
|
|
@ -292,17 +328,13 @@ void NewLogsModel::fetchLogs()
|
|||
} else {
|
||||
params.insert("limit", m_blockSize);
|
||||
if (m_list.count() > 0) {
|
||||
params.insert("offset", m_lastOffset);
|
||||
if (m_lastOffset == 0) {
|
||||
if (m_endTime.isNull()) {
|
||||
m_currentNewest = QDateTime::currentDateTime();
|
||||
} else {
|
||||
m_currentNewest = m_endTime;
|
||||
}
|
||||
if (m_currentNewest.isNull()) {
|
||||
m_currentNewest = QDateTime::currentDateTime();
|
||||
}
|
||||
params.insert("offset", m_lastOffset);
|
||||
params.insert("endTime", m_currentNewest.toMSecsSinceEpoch());
|
||||
m_lastOffset += m_blockSize;
|
||||
}
|
||||
m_lastOffset += m_blockSize;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -367,8 +399,31 @@ void NewLogsModel::logsReply(int commandId, const QVariantMap &data)
|
|||
});
|
||||
m_list.append(entries);
|
||||
endInsertRows();
|
||||
emit entriesAdded(m_list.count(), entries);
|
||||
emit entriesAdded(m_list.count() - entries.count(), entries);
|
||||
}
|
||||
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
void NewLogsModel::newLogEntryReceived(const QVariantMap &map)
|
||||
{
|
||||
QString source = map.value("source").toString();
|
||||
QDateTime timestamp = QDateTime::fromMSecsSinceEpoch(map.value("timestamp").toULongLong());
|
||||
QVariantMap values = map.value("values").toMap();
|
||||
|
||||
if (m_sources.contains(source) && m_sampleRate == SampleRateAny) {
|
||||
NewLogEntry *entry = new NewLogEntry(source, timestamp, values, this);
|
||||
if (m_sortOrder == Qt::AscendingOrder) {
|
||||
beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
|
||||
m_list.append(entry);
|
||||
endInsertRows();
|
||||
emit entriesAdded(m_list.count() - 1, {entry});
|
||||
} else {
|
||||
beginInsertRows(QModelIndex(), 0, 0);
|
||||
m_list.prepend(entry);
|
||||
endInsertRows();
|
||||
emit entriesAdded(0, {entry});
|
||||
}
|
||||
emit countChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,11 @@ class NewLogsModel : public QAbstractListModel, public QQmlParserStatus
|
|||
Q_PROPERTY(SampleRate sampleRate READ sampleRate WRITE setSampleRate NOTIFY sampleRateChanged)
|
||||
Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY sortOrderChanged)
|
||||
|
||||
Q_PROPERTY(int fetchBlockSize READ fetchBlockSize WRITE setFetchBlockSize NOTIFY fetchBlockSizeChanged)
|
||||
Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged)
|
||||
|
||||
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
|
||||
// Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged)
|
||||
|
||||
public:
|
||||
enum Role {
|
||||
|
|
@ -85,6 +87,12 @@ public:
|
|||
|
||||
bool busy() const;
|
||||
|
||||
bool live() const;
|
||||
void setLive(bool live);
|
||||
|
||||
int fetchBlockSize() const;
|
||||
void setFetchBlockSize(int fetchBlockSize);
|
||||
|
||||
Q_INVOKABLE NewLogEntry *get(int index) const;
|
||||
Q_INVOKABLE NewLogEntry *find(const QDateTime ×tamp) const;
|
||||
|
||||
|
|
@ -107,11 +115,15 @@ signals:
|
|||
void sampleRateChanged();
|
||||
void sortOrderChanged();
|
||||
|
||||
void liveChanged();
|
||||
void fetchBlockSizeChanged();
|
||||
|
||||
void entriesAdded(int index, const QList<NewLogEntry*> &entries);
|
||||
void entriesRemoved(int index, int count);
|
||||
|
||||
private slots:
|
||||
void logsReply(int commandId, const QVariantMap &data);
|
||||
void newLogEntryReceived(const QVariantMap &map);
|
||||
|
||||
private:
|
||||
Engine *m_engine = nullptr;
|
||||
|
|
@ -122,6 +134,8 @@ private:
|
|||
|
||||
bool m_busy = false;
|
||||
|
||||
bool m_live = true;
|
||||
|
||||
// For time based sampling
|
||||
QDateTime m_startTime;
|
||||
QDateTime m_endTime;
|
||||
|
|
@ -130,7 +144,7 @@ private:
|
|||
// For continuous scrolling lists
|
||||
bool m_completed = false;
|
||||
bool m_canFetchMore = true;
|
||||
int m_blockSize = 5;
|
||||
int m_blockSize = 50;
|
||||
int m_lastOffset = 0;
|
||||
QDateTime m_currentNewest;
|
||||
|
||||
|
|
|
|||
|
|
@ -973,12 +973,14 @@ Thing* ThingManager::unpackThing(ThingManager *thingManager, const QVariantMap &
|
|||
loggedEventTypeIds.append(uuid.toUuid());
|
||||
}
|
||||
thing->setLoggedEventTypeIds(loggedEventTypeIds);
|
||||
QList<QUuid> loggedActionTypeIds;
|
||||
foreach (const QVariant &uuid, thingMap.value("loggedActionTypeIds").toList()) {
|
||||
loggedActionTypeIds.append(uuid.toUuid());
|
||||
}
|
||||
thing->setLoggedActionTypeIds(loggedActionTypeIds);
|
||||
return thing;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QVariantMap ThingManager::packParam(Param *param)
|
||||
{
|
||||
QVariantMap ret;
|
||||
|
|
|
|||
|
|
@ -244,6 +244,19 @@ void Thing::setLoggedEventTypeIds(const QList<QUuid> &loggedEventTypeIds)
|
|||
}
|
||||
}
|
||||
|
||||
QList<QUuid> Thing::loggedActionTypeIds() const
|
||||
{
|
||||
return m_loggedActionTypeIds;
|
||||
}
|
||||
|
||||
void Thing::setLoggedActionTypeIds(const QList<QUuid> &loggedActionTypeIds)
|
||||
{
|
||||
if (m_loggedActionTypeIds != loggedActionTypeIds) {
|
||||
m_loggedActionTypeIds = loggedActionTypeIds;
|
||||
emit loggedActionTypeIdsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
int Thing::executeAction(const QString &actionName, const QVariantList ¶ms)
|
||||
{
|
||||
ActionType *actionType = m_thingClass->actionTypes()->findByName(actionName);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ class Thing : public QObject
|
|||
Q_PROPERTY(ThingClass *thingClass READ thingClass CONSTANT)
|
||||
Q_PROPERTY(QList<QUuid> loggedStateTypeIds READ loggedStateTypeIds NOTIFY loggedStateTypeIdsChanged)
|
||||
Q_PROPERTY(QList<QUuid> loggedEventTypeIds READ loggedEventTypeIds NOTIFY loggedEventTypeIdsChanged)
|
||||
Q_PROPERTY(QList<QUuid> loggedActionTypeIds READ loggedActionTypeIds NOTIFY loggedActionTypeIdsChanged)
|
||||
|
||||
public:
|
||||
enum ThingSetupStatus {
|
||||
|
|
@ -130,6 +131,9 @@ public:
|
|||
QList<QUuid> loggedEventTypeIds() const;
|
||||
void setLoggedEventTypeIds(const QList<QUuid> &loggedEventTypeIds);
|
||||
|
||||
QList<QUuid> loggedActionTypeIds() const;
|
||||
void setLoggedActionTypeIds(const QList<QUuid> &loggedActionTypeIds);
|
||||
|
||||
ThingClass *thingClass() const;
|
||||
|
||||
Q_INVOKABLE bool hasState(const QUuid &stateTypeId) const;
|
||||
|
|
@ -150,6 +154,7 @@ signals:
|
|||
void statesChanged();
|
||||
void loggedStateTypeIdsChanged();
|
||||
void loggedEventTypeIdsChanged();
|
||||
void loggedActionTypeIdsChanged();
|
||||
void eventTriggered(const QUuid &eventTypeId, const QVariantList ¶ms);
|
||||
|
||||
signals:
|
||||
|
|
@ -168,6 +173,7 @@ protected:
|
|||
ThingClass *m_thingClass = nullptr;
|
||||
QList<QUuid> m_loggedStateTypeIds;
|
||||
QList<QUuid> m_loggedEventTypeIds;
|
||||
QList<QUuid> m_loggedActionTypeIds;
|
||||
|
||||
QList<int> m_pendingActions;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -312,5 +312,7 @@
|
|||
<file>ui/customviews/StateChart.qml</file>
|
||||
<file>ui/devicepages/ThingLogPage.qml</file>
|
||||
<file>ui/devicepages/NotificationsThingPage.qml</file>
|
||||
<file>ui/devicepages/ActionLogPage.qml</file>
|
||||
<file>ui/devicepages/EventLogPage.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,163 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, 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.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Controls.Material 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import Nymea 1.0
|
||||
import "../components"
|
||||
import "../customviews"
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
property Thing thing: null
|
||||
property ActionType actionType: null
|
||||
|
||||
readonly property bool isLogged: thing.loggedActionTypeIds.indexOf(actionType.id) >= 0
|
||||
|
||||
header: NymeaHeader {
|
||||
text: qsTr("History for %1").arg(root.actionType.displayName)
|
||||
onBackPressed: pageStack.pop()
|
||||
|
||||
HeaderButton {
|
||||
imageSource: "delete"
|
||||
visible: root.isLogged
|
||||
onClicked: {
|
||||
var popup = deleteLogsComponent.createObject(root)
|
||||
popup.open()
|
||||
}
|
||||
|
||||
Component {
|
||||
id: deleteLogsComponent
|
||||
NymeaDialog {
|
||||
title: qsTr("Remove logs?")
|
||||
text: qsTr("Do you want to remove the log for this action and disable logging?")
|
||||
standardButtons: Dialog.No | Dialog.Yes
|
||||
onAccepted: engine.thingManager.setActionLogging(root.thing.id, root.actionType.id, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NewLogsModel {
|
||||
id: logsModel
|
||||
engine: _engine
|
||||
source: "action-" + root.thing.id + "-" + root.actionType.name
|
||||
sortOrder: Qt.DescendingOrder
|
||||
}
|
||||
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
visible: root.isLogged
|
||||
model: logsModel
|
||||
clip: true
|
||||
anchors.fill: parent
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
delegate: NymeaItemDelegate {
|
||||
id: delegate
|
||||
width: listView.width
|
||||
height: contentColumn.implicitHeight + Style.margins
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
property NewLogEntry entry: logsModel.get(index)
|
||||
|
||||
contentItem: RowLayout {
|
||||
id: contentColumn
|
||||
anchors { left: parent.left; right: parent.right; margins: app.margins / 2 }
|
||||
ColorIcon {
|
||||
Layout.preferredWidth: Style.iconSize
|
||||
Layout.preferredHeight: width
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: delegate.entry.values.status === "ThingErrorNoError"
|
||||
? Style.iconColor
|
||||
: Style.red
|
||||
name: delegate.entry.values.triggeredBy === "TriggeredByUser"
|
||||
? "account"
|
||||
: "magic"
|
||||
}
|
||||
ColumnLayout {
|
||||
RowLayout {
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: (delegate.entry.values.triggeredBy === "TriggeredByUser" ? qsTr("User action") : qsTr("Automation"))
|
||||
+ " - "
|
||||
+ (delegate.entry.values.status === "ThingErrorNoError" ? qsTr("success") : qsTr("Failure: %1").arg(delegate.entry.values.status))
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
Label {
|
||||
text: Qt.formatDateTime(model.timestamp,"dd.MM.yy - hh:mm:ss")
|
||||
elide: Text.ElideRight
|
||||
font: Style.smallFont
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: {
|
||||
var ret = []
|
||||
var values = JSON.parse(entry.values.params)
|
||||
for (var i = 0; i < root.actionType.paramTypes.count; i++) {
|
||||
var paramType = root.actionType.paramTypes.get(i)
|
||||
ret.push(paramType.displayName + ": " + Types.toUiValue(values[paramType.name], paramType.unit) + " " + Types.toUiUnit(paramType.unit))
|
||||
}
|
||||
return ret.join("<br>")
|
||||
}
|
||||
textFormat: Text.RichText
|
||||
elide: Text.ElideRight
|
||||
font: Style.smallFont
|
||||
visible: text.length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
EmptyViewPlaceholder {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - app.margins * 2
|
||||
title: qsTr("Logging not enabled")
|
||||
text: qsTr("This state is not being logged.")
|
||||
imageSource: "qrc:/styles/%1/logo.svg".arg(styleController.currentStyle)
|
||||
buttonText: qsTr("Enable logging")
|
||||
visible: !root.isLogged
|
||||
onButtonClicked: {
|
||||
print("enabming logging")
|
||||
engine.thingManager.setStateLogging(root.thing.id, root.stateType.id, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,9 +68,12 @@ ThingPageBase {
|
|||
id: logsModel
|
||||
engine: _engine
|
||||
sources: ["event-" + root.thing.id + "-pressed", "event-" + root.thing.id + "-longPressed"]
|
||||
// live: true
|
||||
live: true
|
||||
fetchBlockSize: 200 // As paging doesn't work with multiple sources
|
||||
}
|
||||
|
||||
Component.onCompleted: print("**************** created", logsModel.sources)
|
||||
|
||||
delegate: NymeaItemDelegate {
|
||||
id: entryDelegate
|
||||
width: logView.width
|
||||
|
|
|
|||
|
|
@ -0,0 +1,149 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2023, 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.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Controls.Material 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import Nymea 1.0
|
||||
import "../components"
|
||||
import "../customviews"
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
property Thing thing: null
|
||||
property EventType eventType: null
|
||||
|
||||
readonly property bool isLogged: thing.loggedEventTypeIds.indexOf(eventType.id) >= 0
|
||||
|
||||
header: NymeaHeader {
|
||||
text: qsTr("History for %1").arg(root.eventType.displayName)
|
||||
onBackPressed: pageStack.pop()
|
||||
|
||||
HeaderButton {
|
||||
imageSource: "delete"
|
||||
visible: root.isLogged
|
||||
onClicked: {
|
||||
var popup = deleteLogsComponent.createObject(root)
|
||||
popup.open()
|
||||
}
|
||||
|
||||
Component {
|
||||
id: deleteLogsComponent
|
||||
NymeaDialog {
|
||||
title: qsTr("Remove logs?")
|
||||
text: qsTr("Do you want to remove the log for this event and disable logging?")
|
||||
standardButtons: Dialog.No | Dialog.Yes
|
||||
onAccepted: engine.thingManager.setEventLogging(root.thing.id, root.eventType.id, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NewLogsModel {
|
||||
id: logsModel
|
||||
engine: _engine
|
||||
source: "event-" + root.thing.id + "-" + root.eventType.name
|
||||
sortOrder: Qt.DescendingOrder
|
||||
}
|
||||
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
visible: root.isLogged
|
||||
model: logsModel
|
||||
clip: true
|
||||
anchors.fill: parent
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
delegate: NymeaItemDelegate {
|
||||
id: delegate
|
||||
width: listView.width
|
||||
height: contentColumn.implicitHeight + Style.margins
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
property NewLogEntry entry: logsModel.get(index)
|
||||
|
||||
contentItem: RowLayout {
|
||||
id: contentColumn
|
||||
anchors { left: parent.left; right: parent.right; margins: app.margins / 2 }
|
||||
ColorIcon {
|
||||
Layout.preferredWidth: Style.iconSize
|
||||
Layout.preferredHeight: width
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
name: "event"
|
||||
}
|
||||
ColumnLayout {
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: Qt.formatDateTime(model.timestamp,"dd.MM.yy - hh:mm:ss")
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: {
|
||||
var ret = []
|
||||
var values = JSON.parse(entry.values.params)
|
||||
for (var i = 0; i < root.eventType.paramTypes.count; i++) {
|
||||
var paramType = root.eventType.paramTypes.get(i)
|
||||
ret.push(paramType.displayName + ": " + Types.toUiValue(values[paramType.name], paramType.unit) + " " + Types.toUiUnit(paramType.unit))
|
||||
}
|
||||
return ret.join("<br>")
|
||||
}
|
||||
textFormat: Text.RichText
|
||||
elide: Text.ElideRight
|
||||
font: Style.smallFont
|
||||
visible: text.length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
EmptyViewPlaceholder {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - app.margins * 2
|
||||
title: qsTr("Logging not enabled")
|
||||
text: qsTr("This state is not being logged.")
|
||||
imageSource: "qrc:/styles/%1/logo.svg".arg(styleController.currentStyle)
|
||||
buttonText: qsTr("Enable logging")
|
||||
visible: !root.isLogged
|
||||
onButtonClicked: {
|
||||
print("enabming logging")
|
||||
engine.thingManager.setStateLogging(root.thing.id, root.stateType.id, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +145,13 @@ ThingPageBase {
|
|||
swipe.close();
|
||||
print("opening logs for", delegate.stateType)
|
||||
if (engine.jsonRpcClient.ensureServerVersion("8.0")) {
|
||||
pageStack.push(Qt.resolvedUrl("StateLogPage.qml"), {thing: root.thing, stateType: delegate.stateType})
|
||||
if (delegate.stateType) {
|
||||
pageStack.push(Qt.resolvedUrl("StateLogPage.qml"), {thing: root.thing, stateType: delegate.stateType})
|
||||
} else if (delegate.eventType) {
|
||||
pageStack.push(Qt.resolvedUrl("EventLogPage.qml"), {thing: root.thing, eventType: delegate.eventType})
|
||||
} else if (delegate.actionType) {
|
||||
pageStack.push(Qt.resolvedUrl("ActionLogPage.qml"), {thing: root.thing, actionType: delegate.actionType})
|
||||
}
|
||||
} else {
|
||||
pageStack.push(Qt.resolvedUrl("DeviceLogPage.qml"), {thing: root.thing, filterTypeIds: [model.id]})
|
||||
}
|
||||
|
|
@ -347,10 +353,13 @@ ThingPageBase {
|
|||
}
|
||||
Timer { id: pendingTimer; interval: 1000; repeat: false; running: false }
|
||||
|
||||
Button {
|
||||
text: actionType.displayName
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: actionType.displayName
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
|
||||
onClicked: {
|
||||
if (actionDelegate.actionType.paramTypes.count === 0) {
|
||||
|
|
|
|||
|
|
@ -265,6 +265,7 @@ ThingPageBase {
|
|||
engine: _engine
|
||||
// live: true
|
||||
source: "action-" + root.thing.id + "-notify"
|
||||
sortOrder: Qt.DescendingOrder
|
||||
}
|
||||
|
||||
delegate: BigTile {
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ Page {
|
|||
|
||||
HeaderButton {
|
||||
imageSource: "delete"
|
||||
visible: root.isLogged
|
||||
onClicked: {
|
||||
var popup = deleteLogsComponent.createObject(root)
|
||||
popup.open()
|
||||
|
|
|
|||
Loading…
Reference in New Issue