feat: Add additional utilities for real-time app inspection

- context properties names exposed as a model
- checking if object is a model
- exposing human-readable type name
- exposing role names for models

Closes: https://github.com/status-im/status-desktop/issues/8787
This commit is contained in:
Michał Cieślak 2023-01-13 13:42:30 +01:00 committed by Michał
parent ce5561d3be
commit 0525490619
4 changed files with 119 additions and 12 deletions

View File

@ -0,0 +1,22 @@
#pragma once
#include <QObject>
#include <QAbstractListModel>
class ContextPropertiesModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit ContextPropertiesModel(QObject* parent = nullptr);
static constexpr int NameRole = Qt::UserRole + 1;
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
void addContextProperty(const QString &property);
private:
QStringList m_contextProperties;
};

View File

@ -1,6 +1,9 @@
#pragma once
#include <QObject>
#include <QJSValue>
#include "ContextPropertiesModel.h"
class QQmlApplicationEngine;
class QQmlEngine;
@ -9,21 +12,23 @@ class QJSEngine;
class Monitor : public QObject
{
Q_OBJECT
Q_PROPERTY(QStringList contexPropertiesNames READ getContextPropertiesNames
NOTIFY contextPropertiesNamesChanged)
Q_PROPERTY(ContextPropertiesModel* contexPropertiesModel
READ contexPropertiesModel CONSTANT)
Monitor() = default;
public:
void initialize(QQmlApplicationEngine *engine);
QStringList getContextPropertiesNames() const;
ContextPropertiesModel* contexPropertiesModel();
void addContextPropertyName(const QString &contextPropertyName);
Q_INVOKABLE bool isModel(const QVariant &obj) const;
Q_INVOKABLE QString typeName(const QVariant &obj) const;
Q_INVOKABLE QJSValue modelRoles(QAbstractItemModel *model) const;
static Monitor& instance();
static QObject* qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine);
signals:
void contextPropertiesNamesChanged();
private:
QStringList m_contexPropertiesNames;
ContextPropertiesModel m_contexPropertiesModel;
};

View File

@ -0,0 +1,39 @@
#include "DOtherSide/Status/Monitoring/ContextPropertiesModel.h"
ContextPropertiesModel::ContextPropertiesModel(QObject* parent)
: QAbstractListModel(parent)
{
}
int ContextPropertiesModel::rowCount(const QModelIndex &parent) const
{
return m_contextProperties.size();
}
QVariant ContextPropertiesModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return {};
return m_contextProperties.at(index.row());
}
QHash<int, QByteArray> ContextPropertiesModel::roleNames() const
{
static QHash<int, QByteArray> roles {
{ NameRole, QByteArrayLiteral("name") }
};
return roles;
}
void ContextPropertiesModel::addContextProperty(const QString &property)
{
if (m_contextProperties.contains(property))
return;
const auto currentCount = m_contextProperties.size();
beginInsertRows(QModelIndex(), currentCount, currentCount);
m_contextProperties << property;
endInsertRows();
}

View File

@ -28,18 +28,59 @@ void Monitor::initialize(QQmlApplicationEngine* engine) {
}, Qt::QueuedConnection);
}
QStringList Monitor::getContextPropertiesNames() const
ContextPropertiesModel* Monitor::contexPropertiesModel()
{
return m_contexPropertiesNames;
return &m_contexPropertiesModel;
}
void Monitor::addContextPropertyName(const QString &contextPropertyName)
{
if (m_contexPropertiesNames.contains(contextPropertyName))
return;
m_contexPropertiesModel.addContextProperty(contextPropertyName);
}
m_contexPropertiesNames << contextPropertyName;
emit contextPropertiesNamesChanged();
bool Monitor::isModel(const QVariant &obj) const
{
if (!obj.canConvert<QObject*>())
return false;
return qobject_cast<QAbstractItemModel*>(obj.value<QObject*>()) != nullptr;
}
QString Monitor::typeName(const QVariant &obj) const
{
if (obj.canConvert<QObject*>())
return obj.value<QObject*>()->metaObject()->className();
return QString::fromUtf8(obj.typeName());
}
QJSValue Monitor::modelRoles(QAbstractItemModel *model) const
{
if (model == nullptr)
return {};
QJSEngine *engine = qjsEngine(this);
if (engine == nullptr)
return {};
const auto& roleNames = model->roleNames();
QJSValue array = engine->newArray(roleNames.size());
QList<int> keys = roleNames.keys();
for (auto i = 0; i < keys.size(); i++) {
QJSValue item = engine->newObject();
auto key = keys.at(i);
item.setProperty(QStringLiteral("key"), key);
item.setProperty(QStringLiteral("name"),
QString::fromUtf8(roleNames[key]));
array.setProperty(i, item);
}
return array;
}
Monitor& Monitor::instance()