mirror of
https://github.com/logos-storage/logos-storage-app-skeleton.git
synced 2026-06-13 20:09:28 +00:00
Add list
This commit is contained in:
parent
ca52cf1e81
commit
38d7b0a7e8
@ -67,6 +67,7 @@ LogosResult StorageBackend::init(const QString& configJson = "{}") {
|
||||
setStatus(Running);
|
||||
debug("Storage module started.");
|
||||
QMetaObject::invokeMethod(this, &StorageBackend::downloadManifests, Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(this, &StorageBackend::space, Qt::QueuedConnection);
|
||||
emit startCompleted();
|
||||
}
|
||||
})) {
|
||||
@ -156,6 +157,8 @@ LogosResult StorageBackend::init(const QString& configJson = "{}") {
|
||||
m_uploadStatus = "Upload completed!";
|
||||
emit uploadProgressChanged();
|
||||
emit uploadStatusChanged();
|
||||
|
||||
QMetaObject::invokeMethod(this, &StorageBackend::space, Qt::QueuedConnection);
|
||||
}
|
||||
})) {
|
||||
qWarning() << "StorageWidget: failed to subscribe to storageUploadProgress events";
|
||||
@ -550,13 +553,13 @@ void StorageBackend::remove(const QString& cid) {
|
||||
LogosResult result = m_logos->storage_module.remove(cid);
|
||||
|
||||
if (!result.success) {
|
||||
debug("StorageBackend::remove failed with error=" + result.getError());
|
||||
return;
|
||||
// Log but continue — manifest might not have local data, remove it from the list anyway
|
||||
debug("StorageBackend::remove: storage returned error=" + result.getError() + " (removing from list regardless)");
|
||||
} else {
|
||||
debug("Cid " + cid + " removed from storage.");
|
||||
}
|
||||
|
||||
debug("Cid " + cid + " removed.");
|
||||
|
||||
// Remove from manifests list
|
||||
// Always remove from manifests list
|
||||
for (int i = 0; i < m_manifests.size(); ++i) {
|
||||
if (m_manifests[i].toMap().value("cid").toString() == cid) {
|
||||
m_manifests.removeAt(i);
|
||||
@ -564,6 +567,8 @@ void StorageBackend::remove(const QString& cid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(this, &StorageBackend::space, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void StorageBackend::fetch(const QString& cid) {
|
||||
@ -711,12 +716,33 @@ void StorageBackend::space() {
|
||||
return;
|
||||
}
|
||||
|
||||
debug(QString("Space datasetSize %1").arg(result.getInt("totalBlocks")));
|
||||
debug(QString("Space quotaMaxBytes %1").arg(result.getInt("quotaMaxBytes")));
|
||||
debug(QString("Space quotaUsedBytes %1").arg(result.getInt("quotaUsedBytes")));
|
||||
debug(QString("Space quotaReservedBytes %1").arg(result.getInt("quotaReservedBytes")));
|
||||
qDebug() << "StorageBackend::space raw value:" << result.value;
|
||||
|
||||
static constexpr qint64 DEFAULT_QUOTA = 20LL * 1024 * 1024 * 1024; // 20 GB
|
||||
|
||||
// Check config for a quota-max-bytes override
|
||||
qint64 configQuota = 0;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(m_configJson.toUtf8());
|
||||
if (!doc.isNull()) {
|
||||
configQuota = doc.object().value("quota-max-bytes").toVariant().toLongLong();
|
||||
}
|
||||
|
||||
qint64 apiQuota = result.getInt("quotaMaxBytes");
|
||||
m_quotaMaxBytes = apiQuota > 0 ? apiQuota : (configQuota > 0 ? configQuota : DEFAULT_QUOTA);
|
||||
m_quotaUsedBytes = result.getInt("quotaUsedBytes");
|
||||
m_quotaReservedBytes = result.getInt("quotaReservedBytes");
|
||||
emit quotaChanged();
|
||||
|
||||
debug(QString("Space totalBlocks %1").arg(result.getInt("totalBlocks")));
|
||||
debug(QString("Space quotaMaxBytes %1").arg(m_quotaMaxBytes));
|
||||
debug(QString("Space quotaUsedBytes %1").arg(m_quotaUsedBytes));
|
||||
debug(QString("Space quotaReservedBytes %1").arg(m_quotaReservedBytes));
|
||||
}
|
||||
|
||||
qint64 StorageBackend::quotaMaxBytes() const { return m_quotaMaxBytes; }
|
||||
qint64 StorageBackend::quotaUsedBytes() const { return m_quotaUsedBytes; }
|
||||
qint64 StorageBackend::quotaReservedBytes() const { return m_quotaReservedBytes; }
|
||||
|
||||
void StorageBackend::updateLogLevel(const QString& logLevel) {
|
||||
qDebug() << "StorageBackend::updateLogLevel called with logLevel=" << logLevel;
|
||||
|
||||
|
||||
@ -34,6 +34,9 @@ class StorageBackend : public QObject {
|
||||
Q_PROPERTY(int uploadProgress READ uploadProgress NOTIFY uploadProgressChanged)
|
||||
Q_PROPERTY(QString uploadStatus READ uploadStatus NOTIFY uploadStatusChanged)
|
||||
Q_PROPERTY(QVariantList manifests READ manifests NOTIFY manifestsChanged)
|
||||
Q_PROPERTY(qint64 quotaMaxBytes READ quotaMaxBytes NOTIFY quotaChanged)
|
||||
Q_PROPERTY(qint64 quotaUsedBytes READ quotaUsedBytes NOTIFY quotaChanged)
|
||||
Q_PROPERTY(qint64 quotaReservedBytes READ quotaReservedBytes NOTIFY quotaChanged)
|
||||
|
||||
public:
|
||||
enum StorageStatus { Stopped = 0, Starting, Running, Stopping, Destroyed };
|
||||
@ -46,6 +49,9 @@ class StorageBackend : public QObject {
|
||||
int uploadProgress() const;
|
||||
QString uploadStatus() const;
|
||||
QVariantList manifests() const;
|
||||
qint64 quotaMaxBytes() const;
|
||||
qint64 quotaUsedBytes() const;
|
||||
qint64 quotaReservedBytes() const;
|
||||
|
||||
Q_INVOKABLE static QString defaultDataDir();
|
||||
|
||||
@ -91,6 +97,7 @@ class StorageBackend : public QObject {
|
||||
void uploadProgressChanged();
|
||||
void uploadStatusChanged();
|
||||
void manifestsChanged();
|
||||
void quotaChanged();
|
||||
|
||||
private slots:
|
||||
|
||||
@ -110,4 +117,7 @@ class StorageBackend : public QObject {
|
||||
qint64 m_uploadTotalBytes = 0;
|
||||
qint64 m_uploadedBytes = 0;
|
||||
QVariantList m_manifests;
|
||||
qint64 m_quotaMaxBytes = 0;
|
||||
qint64 m_quotaUsedBytes = 0;
|
||||
qint64 m_quotaReservedBytes = 0;
|
||||
};
|
||||
|
||||
@ -128,6 +128,17 @@ Rectangle {
|
||||
function updateLogLevel(logLevel) {}
|
||||
|
||||
property var manifests: []
|
||||
property var quotaMaxBytes: 20 * 1024 * 1024 * 1024 // 20 GB default
|
||||
property var quotaUsedBytes: 0
|
||||
property var quotaReservedBytes: 0
|
||||
}
|
||||
|
||||
function formatBytes(bytes) {
|
||||
if (bytes <= 0) return "0 B"
|
||||
if (bytes < 1024) return bytes + " B"
|
||||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB"
|
||||
if (bytes < 1024 * 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(1) + " MB"
|
||||
return (bytes / (1024 * 1024 * 1024)).toFixed(2) + " GB"
|
||||
}
|
||||
|
||||
Text {
|
||||
@ -397,11 +408,96 @@ Rectangle {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
// ── Disk space bar ────────────────────────────────────────────────────
|
||||
Item {
|
||||
id: spaceBarSection
|
||||
anchors.top: manifestsTitle.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width - 40
|
||||
height: root.backend.quotaMaxBytes > 0 ? 36 : 20
|
||||
|
||||
readonly property real total: root.backend.quotaMaxBytes
|
||||
readonly property real used: root.backend.quotaUsedBytes
|
||||
readonly property real reserved: root.backend.quotaReservedBytes
|
||||
|
||||
// No quota configured
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "No quota configured"
|
||||
color: "#555555"
|
||||
font.pixelSize: 11
|
||||
visible: spaceBarSection.total <= 0
|
||||
}
|
||||
|
||||
// Background track
|
||||
Rectangle {
|
||||
id: spaceBarTrack
|
||||
visible: spaceBarSection.total > 0
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: 14
|
||||
radius: 7
|
||||
color: "#2a2a2a"
|
||||
border.color: "#3a3a3a"
|
||||
border.width: 1
|
||||
clip: true
|
||||
|
||||
// Used (green)
|
||||
Rectangle {
|
||||
width: Math.min(parent.width * (spaceBarSection.used / spaceBarSection.total), parent.width)
|
||||
height: parent.height
|
||||
radius: parent.radius
|
||||
color: "#4CAF50"
|
||||
}
|
||||
|
||||
// Reserved (orange), stacked after used
|
||||
Rectangle {
|
||||
x: parent.width * (spaceBarSection.used / spaceBarSection.total)
|
||||
width: Math.min(parent.width * (spaceBarSection.reserved / spaceBarSection.total),
|
||||
parent.width - x)
|
||||
height: parent.height
|
||||
color: "#FF9800"
|
||||
}
|
||||
}
|
||||
|
||||
// Labels
|
||||
Row {
|
||||
visible: spaceBarSection.total > 0
|
||||
anchors.top: spaceBarTrack.bottom
|
||||
anchors.topMargin: 4
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 16
|
||||
|
||||
Text {
|
||||
text: "Used: " + root.formatBytes(spaceBarSection.used)
|
||||
color: "#4CAF50"
|
||||
font.pixelSize: 10
|
||||
}
|
||||
Text {
|
||||
text: "Reserved: " + root.formatBytes(spaceBarSection.reserved)
|
||||
color: "#FF9800"
|
||||
font.pixelSize: 10
|
||||
}
|
||||
Text {
|
||||
text: "Free: " + root.formatBytes(spaceBarSection.total - spaceBarSection.used - spaceBarSection.reserved)
|
||||
color: "#888888"
|
||||
font.pixelSize: 10
|
||||
}
|
||||
Text {
|
||||
text: "Total: " + root.formatBytes(spaceBarSection.total)
|
||||
color: "#555555"
|
||||
font.pixelSize: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: manifestInputRow
|
||||
spacing: 8
|
||||
anchors.top: manifestsTitle.bottom
|
||||
anchors.topMargin: 8
|
||||
anchors.top: spaceBarSection.bottom
|
||||
anchors.topMargin: 16
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
TextField {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user