From e356329dc93d0dc928d4de3039b83fbecb8d9bc5 Mon Sep 17 00:00:00 2001 From: Wang Zichong Date: Tue, 7 Jul 2026 17:30:04 +0800 Subject: [PATCH] get basic quick item info --- bridge/src/main.cpp | 2 ++ bridge/src/scenegraph_tools.cpp | 60 +++++++++++++++++++++++++++++++++ bridge/src/scenegraph_tools.h | 2 ++ 3 files changed, 64 insertions(+) diff --git a/bridge/src/main.cpp b/bridge/src/main.cpp index 2910f8b..1444f64 100644 --- a/bridge/src/main.cpp +++ b/bridge/src/main.cpp @@ -88,6 +88,8 @@ int main(int argc, char **argv) { QStringLiteral("selectQuickWindow"), QStringLiteral("Select a Quick window (by index into listQuickWindows) so the scene graph is introspected for it") }, { QStringLiteral("selectQuickWindow/index"), QStringLiteral("0-based index of the window in listQuickWindows") }, { QStringLiteral("listScenegraphNodes"), QStringLiteral("List the QSGNode tree of the selected Quick window") }, + // QML item tree + { QStringLiteral("listQuickItems"), QStringLiteral("List the QQuickItem tree (QML item types, names, hierarchy)") }, // SG node selection // TODO: re-enable when the selection-sync / sub-model-population bug is fixed // { QStringLiteral("selectScenegraphNode"), QStringLiteral("Select a SG node by address (from listScenegraphNodes) so geometry/material sub-models populate for it") }, diff --git a/bridge/src/scenegraph_tools.cpp b/bridge/src/scenegraph_tools.cpp index 5b4f29e..9aae32a 100644 --- a/bridge/src/scenegraph_tools.cpp +++ b/bridge/src/scenegraph_tools.cpp @@ -28,6 +28,7 @@ // Model registration names (from plugins/quickinspector/quickinspector.cpp). static const char *kQuickWindowModel = "com.kdab.GammaRay.QuickWindowModel"; +static const char *kQuickItemModel = "com.kdab.GammaRay.QuickItemModel"; static const char *kQuickSceneGraphModel = "com.kdab.GammaRay.QuickSceneGraphModel"; static const char *kBaseName = "com.kdab.GammaRay.QuickSceneGraph"; static const char *kMaterialIface = "com.kdab.GammaRay.MaterialExtensionInterface"; @@ -84,6 +85,46 @@ static QJsonArray walkChildren(const QAbstractItemModel *m, const QModelIndex &p return out; } +// ItemFlags role value (QuickItemModelRole::ItemFlags = ObjectModel::UserRole = 261) +static constexpr int kItemFlagsRole = 261; + +static QJsonObject flagsToJson(int flags) +{ + QJsonObject f; + f.insert(QStringLiteral("invisible"), (flags & 1) != 0); + f.insert(QStringLiteral("zeroSize"), (flags & 2) != 0); + f.insert(QStringLiteral("partiallyOutOfView"), (flags & 4) != 0); + f.insert(QStringLiteral("outOfView"), (flags & 8) != 0); + f.insert(QStringLiteral("hasFocus"), (flags & 16) != 0); + f.insert(QStringLiteral("hasActiveFocus"), (flags & 32) != 0); + f.insert(QStringLiteral("justReceivedEvent"),(flags & 64) != 0); + f.insert(QStringLiteral("value"), flags); + return f; +} + +static QJsonArray walkItemChildren(const QAbstractItemModel *m, const QModelIndex &parent, int depth) +{ + QJsonArray out; + if (depth <= 0) + return out; + for (int r = 0; r < m->rowCount(parent); ++r) { + const QModelIndex idx = m->index(r, 0, parent); + const QString name = m->data(idx, Qt::DisplayRole).toString(); + const QModelIndex typeIdx = m->index(r, 1, parent); + const QString type = m->data(typeIdx, Qt::DisplayRole).toString(); + const int flags = m->data(idx, kItemFlagsRole).toInt(); + QJsonObject node; + node.insert(QStringLiteral("name"), name); + node.insert(QStringLiteral("type"), type); + if (flags) + node.insert(QStringLiteral("flags"), flagsToJson(flags)); + if (m->hasChildren(idx)) + node.insert(QStringLiteral("children"), walkItemChildren(m, idx, depth - 1)); + out.append(node); + } + return out; +} + static void primeTree(const QAbstractItemModel *m, const QModelIndex &parent, int depth) { if (depth <= 0) @@ -319,6 +360,25 @@ QString SceneGraphTools::selectQuickWindow(int index) const }).toJson(QJsonDocument::Compact)); } +// --- QML item tree --- + +QString SceneGraphTools::listQuickItems() const +{ + if (const QString e = ensureSession(); !e.isEmpty()) + return e; + + auto *m = m_session->model(QString::fromUtf8(kQuickItemModel)); + if (!m) + return QString::fromUtf8(QJsonDocument(errorJson( + QStringLiteral("QuickItemModel not available (no Quick app attached?)"))).toJson(QJsonDocument::Compact)); + + // Prime the tree and wait for data to populate + primeAndWait(m, 6, 300, 500); + + const QJsonArray tree = walkItemChildren(m, QModelIndex(), 16); + return QString::fromUtf8(QJsonDocument(tree).toJson(QJsonDocument::Compact)); +} + QString SceneGraphTools::listScenegraphNodes() const { if (const QString e = ensureSession(); !e.isEmpty()) diff --git a/bridge/src/scenegraph_tools.h b/bridge/src/scenegraph_tools.h index 0adde06..6ef8d0a 100644 --- a/bridge/src/scenegraph_tools.h +++ b/bridge/src/scenegraph_tools.h @@ -52,6 +52,8 @@ public: // --- Window-level navigation --- Q_INVOKABLE QString listQuickWindows() const; Q_INVOKABLE QString selectQuickWindow(int index) const; + // --- QML item tree --- + Q_INVOKABLE QString listQuickItems() const; // --- SceneGraph navigation --- Q_INVOKABLE QString listScenegraphNodes() const;