diff --git a/src/StorageBackend.cpp b/src/StorageBackend.cpp index 2362797..4eec6d3 100644 --- a/src/StorageBackend.cpp +++ b/src/StorageBackend.cpp @@ -66,6 +66,7 @@ LogosResult StorageBackend::init(const QString& configJson = "{}") { } else { setStatus(Running); debug("Storage module started."); + QMetaObject::invokeMethod(this, &StorageBackend::downloadManifests, Qt::QueuedConnection); emit startCompleted(); } })) { @@ -631,18 +632,38 @@ void StorageBackend::downloadManifest(const QString& cid) { return; } - debug("Manifest tree cid: " + result.getString("treeCid")); - debug(QString("Manifest datasetSize %1").arg(result.getInt("datasetSize"))); - debug(QString("Manifest blockSize %1").arg(result.getInt("blockSize"))); - debug("Manifest filename: " + result.getString("filename")); - debug("Manifest mimetype: " + result.getString("mimetype")); + QString treeCid = result.getString("treeCid"); + qint64 datasetSize = result.getInt("datasetSize"); + qint64 blockSize = result.getInt("blockSize"); + QString filename = result.getString("filename"); + QString mimetype = result.getString("mimetype"); + + debug("Manifest tree cid: " + treeCid); + debug(QString("Manifest datasetSize %1").arg(datasetSize)); + debug(QString("Manifest blockSize %1").arg(blockSize)); + debug("Manifest filename: " + filename); + debug("Manifest mimetype: " + mimetype); + + // Add to manifests list + QVariantMap manifest; + manifest["cid"] = cid; + manifest["treeCid"] = treeCid; + manifest["filename"] = filename; + manifest["mimetype"] = mimetype; + manifest["datasetSize"] = datasetSize; + manifest["blockSize"] = blockSize; + + m_manifests.append(manifest); + emit manifestsChanged(); } +QVariantList StorageBackend::manifests() const { return m_manifests; } + void StorageBackend::downloadManifests() { qDebug() << "StorageBackend::downloadManifests called"; LogosResult result = m_logos->storage_module.manifests(); - QString error = result.getError(); + if (!result.success) { debug("StorageBackend::downloadManifests failed with error=" + result.getError()); return; @@ -650,22 +671,25 @@ void StorageBackend::downloadManifests() { QVariantList manifestsList = result.getList(); int count = manifestsList.size(); - debug(QString("Found %1 manifests").arg(count)); - // for (const QVariant& manifestVariant : manifestsList) { - // QVariantMap manifest = manifestVariant.toMap(); + m_manifests.clear(); - // QString cid = manifest["cid"].toString(); - // QString treeCid = manifest["treeCid"].toString(); - // QString filename = manifest["filename"].toString(); - // qint64 datasetSize = manifest["datasetSize"].toLongLong(); + for (const QVariant& manifestVariant : manifestsList) { + QVariantMap src = manifestVariant.toMap(); - // debug(QString("Manifest: %1, treeCid: %2, size: %3") - // .arg(filename) - // .arg(treeCid.isEmpty() ? "EMPTY" : treeCid) - // .arg(datasetSize)); - // } + QVariantMap manifest; + manifest["cid"] = src.value("cid").toString(); + manifest["treeCid"] = src.value("treeCid").toString(); + manifest["filename"] = src.value("filename").toString(); + manifest["mimetype"] = src.value("mimetype").toString(); + manifest["datasetSize"] = src.value("datasetSize").toLongLong(); + manifest["blockSize"] = src.value("blockSize").toLongLong(); + + m_manifests.append(manifest); + } + + emit manifestsChanged(); } void StorageBackend::space() { diff --git a/src/StorageBackend.h b/src/StorageBackend.h index a920854..79fb1ce 100644 --- a/src/StorageBackend.h +++ b/src/StorageBackend.h @@ -33,6 +33,7 @@ class StorageBackend : public QObject { Q_PROPERTY(QString configJson READ configJson NOTIFY configJsonChanged) Q_PROPERTY(int uploadProgress READ uploadProgress NOTIFY uploadProgressChanged) Q_PROPERTY(QString uploadStatus READ uploadStatus NOTIFY uploadStatusChanged) + Q_PROPERTY(QVariantList manifests READ manifests NOTIFY manifestsChanged) public: enum StorageStatus { Stopped = 0, Starting, Running, Stopping, Destroyed }; @@ -44,6 +45,7 @@ class StorageBackend : public QObject { QString configJson() const; int uploadProgress() const; QString uploadStatus() const; + QVariantList manifests() const; Q_INVOKABLE static QString defaultDataDir(); @@ -88,6 +90,7 @@ class StorageBackend : public QObject { void configJsonChanged(); void uploadProgressChanged(); void uploadStatusChanged(); + void manifestsChanged(); private slots: @@ -106,4 +109,5 @@ class StorageBackend : public QObject { QString m_uploadStatus = ""; qint64 m_uploadTotalBytes = 0; qint64 m_uploadedBytes = 0; + QVariantList m_manifests; }; diff --git a/src/qml/StorageView.qml b/src/qml/StorageView.qml index 1b95f16..181683e 100644 --- a/src/qml/StorageView.qml +++ b/src/qml/StorageView.qml @@ -124,6 +124,8 @@ Rectangle { function space() {} function updateLogLevel(logLevel) {} + + property var manifests: [] } Text { @@ -392,6 +394,144 @@ Rectangle { anchors.topMargin: 10 } + // ── Manifests section ────────────────────────────────────────────────── + Text { + id: manifestsTitle + text: "Manifests" + color: "white" + font.pixelSize: 14 + font.bold: true + anchors.top: downloadManifestsButton.bottom + anchors.topMargin: 30 + anchors.horizontalCenter: parent.horizontalCenter + } + + Row { + id: manifestInputRow + spacing: 8 + anchors.top: manifestsTitle.bottom + anchors.topMargin: 8 + anchors.horizontalCenter: parent.horizontalCenter + + TextField { + id: manifestCidField + width: 380 + placeholderText: "Enter CID to download manifest" + placeholderTextColor: "#999999" + color: "#000000" + selectByMouse: true + } + + Button { + id: addManifestButton + text: "Download Manifest" + enabled: root.isRunning() && manifestCidField.text.length > 0 + onClicked: { + root.backend.downloadManifest(manifestCidField.text) + manifestCidField.clear() + } + } + } + + // Table header + Rectangle { + id: manifestTableHeader + anchors.top: manifestInputRow.bottom + anchors.topMargin: 8 + anchors.left: manifestInputRow.left + anchors.right: manifestInputRow.right + height: 28 + color: "#222222" + radius: 2 + + Row { + anchors.fill: parent + anchors.leftMargin: 6 + + Text { width: 200; text: "CID"; color: "#aaaaaa"; font.pixelSize: 11; font.bold: true; elide: Text.ElideRight; anchors.verticalCenter: parent.verticalCenter } + Text { width: 140; text: "Filename"; color: "#aaaaaa"; font.pixelSize: 11; font.bold: true; elide: Text.ElideRight; anchors.verticalCenter: parent.verticalCenter } + Text { width: 100; text: "MIME type"; color: "#aaaaaa"; font.pixelSize: 11; font.bold: true; elide: Text.ElideRight; anchors.verticalCenter: parent.verticalCenter } + Text { width: 90; text: "Size (bytes)"; color: "#aaaaaa"; font.pixelSize: 11; font.bold: true; elide: Text.ElideRight; anchors.verticalCenter: parent.verticalCenter } + } + } + + Rectangle { + id: manifestTableContainer + anchors.top: manifestTableHeader.bottom + anchors.left: manifestTableHeader.left + anchors.right: manifestTableHeader.right + height: 180 + color: "#111111" + border.color: "#333333" + border.width: 1 + clip: true + + ListView { + id: manifestListView + anchors.fill: parent + model: root.backend.manifests + clip: true + + delegate: Rectangle { + width: manifestListView.width + height: 28 + color: index % 2 === 0 ? "#181818" : "#1e1e1e" + + Row { + anchors.fill: parent + anchors.leftMargin: 6 + spacing: 0 + + Text { + width: 200 + text: modelData["cid"] ?? "" + color: "#dddddd" + font.pixelSize: 11 + font.family: "monospace" + elide: Text.ElideMiddle + anchors.verticalCenter: parent.verticalCenter + ToolTip.visible: hovered + ToolTip.text: modelData["cid"] ?? "" + HoverHandler {} + } + Text { + width: 140 + text: modelData["filename"] ?? "" + color: "#dddddd" + font.pixelSize: 11 + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + Text { + width: 100 + text: modelData["mimetype"] ?? "" + color: "#dddddd" + font.pixelSize: 11 + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + Text { + width: 90 + text: modelData["datasetSize"] ?? "" + color: "#dddddd" + font.pixelSize: 11 + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } + } + } + + Text { + anchors.centerIn: parent + text: "No manifests yet" + color: "#555555" + font.pixelSize: 12 + visible: manifestListView.count === 0 + } + } + } + + // ── Log level section ────────────────────────────────────────────────── TextField { id: logLevelField placeholderTextColor: "#999999" @@ -399,8 +539,8 @@ Rectangle { color: "black" // text: root.downloadCid onTextChanged: root.logLevel = text - anchors.top: downloadManifestsButton.bottom - anchors.topMargin: 50 + anchors.top: manifestTableContainer.bottom + anchors.topMargin: 30 anchors.horizontalCenter: parent.horizontalCenter }