From 1ef920e45659688b33fccdb70d2155f710535681 Mon Sep 17 00:00:00 2001 From: jolavillette Date: Sat, 16 May 2026 16:02:09 +0200 Subject: [PATCH] GUI: Refactored RemoteDirModel to rely on unified engine statistics --- .../gui/FileTransfer/SharedFilesDialog.cpp | 3 +- retroshare-gui/src/gui/RemoteDirModel.cpp | 229 ++---------------- retroshare-gui/src/gui/RemoteDirModel.h | 33 +-- 3 files changed, 31 insertions(+), 234 deletions(-) diff --git a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp index 317054dc9..cd8e774cc 100644 --- a/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp +++ b/retroshare-gui/src/gui/FileTransfer/SharedFilesDialog.cpp @@ -148,7 +148,8 @@ protected: return false; } - if (!m_dirModel->hasUploads(ref)) { + DirDetails details; + if (!m_dirModel->requestDirDetails(ref, m_dirModel->isRemote(), details) || details.uploads == 0) { return false; } } diff --git a/retroshare-gui/src/gui/RemoteDirModel.cpp b/retroshare-gui/src/gui/RemoteDirModel.cpp index 98a221b89..69167c519 100644 --- a/retroshare-gui/src/gui/RemoteDirModel.cpp +++ b/retroshare-gui/src/gui/RemoteDirModel.cpp @@ -39,6 +39,8 @@ #include #include +#include "util/rsdebug.h" + #include #include #include @@ -149,104 +151,10 @@ void RetroshareDirModel::treeStyle() peerIcon = FilesDefs::getIconFromQtResourcePath(":/icons/folder-account.svg"); } -void TreeStyle_RDM::recalculateDirectoryTotals() -{ - m_folderTotals.clear(); - - // Stats are primarily calculated for local files. - // For remote files, branch stats are limited by what the core provides. - if(RemoteMode) - return; - - // Start recursion from Root (NULL) - collectStatsRecursive(NULL); -} - -TreeStyle_RDM::FolderStats TreeStyle_RDM::collectStatsRecursive(void* ref) -{ - FolderStats stats; - - // CRITICAL FIX: Safety check for NULL pointers (except for Root which can be NULL start) - // Actually requestDirDetails handles NULL ref for Root correctly. - - DirDetails details; - if(!requestDirDetails(ref, RemoteMode, details)) - { - return stats; - } - - // If it's a file, we return its stats - if(details.type == DIR_TYPE_FILE || details.type == DIR_TYPE_EXTRA_FILE) - { - stats.size = details.size; - stats.count = 1; - stats.uploads = rsFiles->getCumulativeUpload(details.hash); - - // Special handling for Extra Files (virtual root) - if (details.type == DIR_TYPE_EXTRA_FILE) - { - m_folderTotals["!!RS_EXTRA_FILES_ROOT!!"] += stats; - } - - return stats; - } - - // If it's a directory or root node, we dive into children - if(details.type == DIR_TYPE_DIR || details.type == DIR_TYPE_ROOT || details.type == DIR_TYPE_PERSON) - { - for(const auto& child : details.children) - { - stats += collectStatsRecursive(child.ref); - } - - // If this is a real directory, store the aggregated totals - if(details.type == DIR_TYPE_DIR) - { - QString path = QDir::cleanPath(QString::fromUtf8(details.path.c_str())); - m_folderTotals[path] = stats; - } - } - - return stats; -} - -// MODIFICATION D: Check if a specific node or any of its descendants have uploads -// hasUploads for TreeStyle - Defensive Check -bool TreeStyle_RDM::hasUploads(void *ref) const -{ - // CRITICAL FIX: Safety check for NULL pointers - if (ref == NULL) { - return false; - } - - DirDetails details; - if (!requestDirDetails(ref, RemoteMode, details)) return false; - - if (details.type == DIR_TYPE_FILE || details.type == DIR_TYPE_EXTRA_FILE) { - return rsFiles->getCumulativeUpload(details.hash) > 0; - } - - if (details.type == DIR_TYPE_PERSON && details.id != rsPeers->getOwnId()) { - auto it = m_folderTotals.find("!!RS_EXTRA_FILES_ROOT!!"); - return (it != m_folderTotals.end()) ? (it->second.uploads > 0) : false; - } - - if (details.type == DIR_TYPE_DIR) { - QString path = QDir::cleanPath(QString::fromUtf8(details.path.c_str())); - auto it = m_folderTotals.find(path); - return (it != m_folderTotals.end()) ? (it->second.uploads > 0) : false; - } - - return true; -} - void TreeStyle_RDM::update() { preMods() ; - - // Recalculate totals before notifying view update - recalculateDirectoryTotals(); - + RetroshareDirModel::update(); postMods() ; } void TreeStyle_RDM::updateRef(const QModelIndex& indx) const @@ -586,7 +494,7 @@ void FlatStyle_RDM::update() // MODIFICATION: Do NOT clear cache here. - // We want hasUploads() to be fast even during the re-crawl. + // We want data access to be fast even during the re-crawl. // updateRefs will overwrite cache entries as it finds files. // { // RS_STACK_MUTEX(_ref_mutex); @@ -715,32 +623,10 @@ QVariant TreeStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails& case REMOTEDIRMODEL_COLUMN_NAME: return (RemoteMode)?(QString::fromUtf8(rsPeers->getPeerName(details.id).c_str())):tr("My files"); case REMOTEDIRMODEL_COLUMN_FILENB: { - SharedDirStats stats ; - if(RemoteMode) - rsFiles->getSharedDirStatistics(details.id,stats) ; - else if(details.id == rsPeers->getOwnId()) - rsFiles->getSharedDirStatistics(rsPeers->getOwnId(),stats) ; - else - { - auto it = m_folderTotals.find("!!RS_EXTRA_FILES_ROOT!!"); - return (it != m_folderTotals.end()) ? (qulonglong)it->second.count : (qulonglong)0; - } - - return (qulonglong) stats.total_number_of_files; + return (qulonglong) details.count; } case REMOTEDIRMODEL_COLUMN_SIZE: { - SharedDirStats stats ; - if(RemoteMode) - rsFiles->getSharedDirStatistics(details.id,stats) ; - else if(details.id == rsPeers->getOwnId()) - rsFiles->getSharedDirStatistics(rsPeers->getOwnId(),stats) ; - else - { - auto it = m_folderTotals.find("!!RS_EXTRA_FILES_ROOT!!"); - return (it != m_folderTotals.end()) ? (qulonglong)it->second.size : (qulonglong)0; - } - - return (qulonglong) stats.total_shared_size; + return (qulonglong) details.size; } case REMOTEDIRMODEL_COLUMN_AGE: return details.max_mtime; @@ -784,19 +670,11 @@ QVariant TreeStyle_RDM::sortRole(const QModelIndex& /*index*/,const DirDetails& return QString::fromUtf8(details.name.c_str()); case REMOTEDIRMODEL_COLUMN_FILENB: { - if (RemoteMode) - return (qulonglong)details.count; - - auto it = m_folderTotals.find(path); - return (it != m_folderTotals.end()) ? (qulonglong)it->second.count : (qulonglong)0; + return (qulonglong)details.count; } case REMOTEDIRMODEL_COLUMN_SIZE: { - if (RemoteMode) - return (qulonglong)details.size; - - auto it = m_folderTotals.find(path); - return (it != m_folderTotals.end()) ? (qulonglong)it->second.size : (qulonglong)0; + return (qulonglong)details.size; } case REMOTEDIRMODEL_COLUMN_AGE: return details.max_mtime; @@ -1647,44 +1525,21 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details, int coln) const case REMOTEDIRMODEL_COLUMN_FILENB: { - SharedDirStats stats; - if(RemoteMode) - rsFiles->getSharedDirStatistics(details.id, stats) ; - else if(details.id == rsPeers->getOwnId()) - rsFiles->getSharedDirStatistics(rsPeers->getOwnId(), stats) ; - else { - // Specific handling for "Temporary shared files" node (Extra files root) - auto it = m_folderTotals.find("!!RS_EXTRA_FILES_ROOT!!"); - uint32_t nb = (it != m_folderTotals.end()) ? it->second.count : 0; - if(nb > 1) return QString::number(nb) + " " + tr("Files"); - if(nb == 1) return QString::number(nb) + " " + tr("File"); - return tr("Empty"); - } - - if(stats.total_number_of_files > 0) - return QString::number(stats.total_number_of_files) + " " + (stats.total_number_of_files > 1 ? tr("Files") : tr("File")); + if(details.count > 0) + return QString::number(details.count) + " " + (details.count > 1 ? tr("Files") : tr("File")); return tr("Empty"); } break; + break; case REMOTEDIRMODEL_COLUMN_SIZE: { - SharedDirStats stats ; - if(RemoteMode) - rsFiles->getSharedDirStatistics(details.id,stats) ; - else if(details.id == rsPeers->getOwnId()) - rsFiles->getSharedDirStatistics(rsPeers->getOwnId(),stats) ; - else - { - auto it = m_folderTotals.find("!!RS_EXTRA_FILES_ROOT!!"); - return misc::friendlyUnit((it != m_folderTotals.end()) ? it->second.size : 0); - } - - if(stats.total_shared_size > 0) - return misc::friendlyUnit(stats.total_shared_size) ; + if(details.size > 0) + return misc::friendlyUnit(details.size) ; return QString(); } break; + break; case REMOTEDIRMODEL_COLUMN_AGE: { @@ -1699,17 +1554,10 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details, int coln) const case REMOTEDIRMODEL_COLUMN_UPLOADED: { - if(!RemoteMode && details.id == rsPeers->getOwnId()) - { - uint64_t n = rsFiles->getCumulativeUploadNum(); - if(n) - return QString(misc::friendlyUnit(rsFiles->getCumulativeUploadAll()) + QString(" - %1 files").arg(n)); - else - return QString("-"); - } - return QString(); + return (details.uploads > 0) ? misc::friendlyUnit(details.uploads) : QString(); } break; + break; default: return QString(); } @@ -1735,8 +1583,7 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details, int coln) const } case REMOTEDIRMODEL_COLUMN_UPLOADED: { - uint64_t x = rsFiles->getCumulativeUpload(details.hash); - return x ? misc::friendlyUnit(x) : QString(); + return (details.uploads > 0) ? misc::friendlyUnit(details.uploads) : QString(); } break; default: return QVariant(); @@ -1745,34 +1592,25 @@ QVariant TreeStyle_RDM::displayRole(const DirDetails& details, int coln) const else if (details.type == DIR_TYPE_DIR) /* Directory */ { QString path = QDir::cleanPath(QString::fromUtf8(details.path.c_str())); + + switch(coln) { case REMOTEDIRMODEL_COLUMN_NAME: return QString::fromUtf8(details.name.c_str()); case REMOTEDIRMODEL_COLUMN_FILENB: { - if (RemoteMode) { - return QString::number(details.count) + " " + (details.count > 1 ? tr("Files") : tr("File")); - } - auto it = m_folderTotals.find(path); - uint32_t totalFiles = (it != m_folderTotals.end()) ? it->second.count : 0; - return QString::number(totalFiles) + " " + (totalFiles > 1 ? tr("Files") : tr("File")); + return QString::number(details.count) + " " + (details.count > 1 ? tr("Files") : tr("File")); } case REMOTEDIRMODEL_COLUMN_SIZE: { - if (RemoteMode) - return misc::friendlyUnit(details.size); - - auto it = m_folderTotals.find(path); - return misc::friendlyUnit((it != m_folderTotals.end()) ? it->second.size : 0); + return misc::friendlyUnit(details.size); } case REMOTEDIRMODEL_COLUMN_AGE: return misc::timeRelativeToNow(details.max_mtime); case REMOTEDIRMODEL_COLUMN_FRIEND_ACCESS: return getFlagsString(details.flags); case REMOTEDIRMODEL_COLUMN_WN_VISU_DIR: return getGroupsString(details.flags,details.parent_groups) ; case REMOTEDIRMODEL_COLUMN_UPLOADED: { - auto it = m_folderTotals.find(path); - uint64_t totalUpload = (it != m_folderTotals.end()) ? it->second.uploads : 0; - return totalUpload > 0 ? misc::friendlyUnit(totalUpload) : ""; + return (details.uploads > 0) ? misc::friendlyUnit(details.uploads) : QString(); } break; default: return QVariant(); @@ -1960,7 +1798,7 @@ void FlatStyle_RDM::updateRefs() uint64_t x = rsFiles->getCumulativeUpload(details.hash); cfd.uploadStr = x ? misc::friendlyUnit(x) : QString(); cfd.uploads = x; - cfd.hasUploads = (x > 0); + cfd.size = details.size; cfd.mtime = details.max_mtime; @@ -2013,26 +1851,5 @@ void TreeStyle_RDM::showEmpty(const bool value) update(); } -// hasUploads for FlatStyle - Defensive Check -bool FlatStyle_RDM::hasUploads(void *ref) const -{ - if (ref == NULL) return false; - RS_STACK_MUTEX(_ref_mutex); - auto it = m_cache.find(ref); - if (it != m_cache.end()) - { - return it->second.hasUploads; - } - - // Fallback if not in cache (should be rare in steady state) - DirDetails details; - if (!requestDirDetails(ref, RemoteMode, details)) return false; - - if (details.type == DIR_TYPE_FILE || details.type == DIR_TYPE_EXTRA_FILE) { - return rsFiles->getCumulativeUpload(details.hash) > 0; - } - - return false; -} diff --git a/retroshare-gui/src/gui/RemoteDirModel.h b/retroshare-gui/src/gui/RemoteDirModel.h index b0e1f05e4..bf69e862d 100644 --- a/retroshare-gui/src/gui/RemoteDirModel.h +++ b/retroshare-gui/src/gui/RemoteDirModel.h @@ -81,11 +81,11 @@ class RetroshareDirModel : public QAbstractItemModel void getFilePaths(const QModelIndexList &list, std::list &fullpaths); void getFilePath(const QModelIndex& index, std::string& fullpath); void changeAgeIndicator(uint32_t indicator) { ageIndicator = indicator; } + bool isRemote() const { return RemoteMode; } bool requestDirDetails(void *ref, bool remote,DirDetails& d) const; - // MODIFICATION A: Virtual method to check if a branch has cumulative uploads - virtual bool hasUploads(void *ref) const = 0; + virtual void update() {} virtual void updateRef(const QModelIndex&) const =0; @@ -211,8 +211,7 @@ class TreeStyle_RDM: public RetroshareDirModel virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - // MODIFICATION B: Implementation for Tree Style - virtual bool hasUploads(void *ref) const; + private slots: void showEmpty(const bool value); @@ -221,28 +220,9 @@ class TreeStyle_RDM: public RetroshareDirModel QAction *_showEmptyAct; bool _showEmpty; - // Helper to calculate total recursive statistics per directory (Files count, Size, Uploads) - void recalculateDirectoryTotals(); + - private: - struct FolderStats { - uint64_t size; - uint32_t count; - uint64_t uploads; - - FolderStats() : size(0), count(0), uploads(0) {} - FolderStats& operator+=(const FolderStats& s) { - size += s.size; - count += s.count; - uploads += s.uploads; - return *this; - } - }; - - std::map m_folderTotals; // Key: clean path, Val: recursive stats - - FolderStats collectStatsRecursive(void* ref); protected: mutable std::vector _parentRow ; // used to store the real parent row for non empty child @@ -273,8 +253,7 @@ class FlatStyle_RDM: public RetroshareDirModel virtual void preMods(); virtual void postMods();/* Callback from Core */ virtual void updateRef(const QModelIndex&) const {} - // MODIFICATION H: Implement hasUploads for Flat Style to fix compilation - virtual bool hasUploads(void *ref) const; + // MODIFICATION: Override data() to use internal cache for Flat View virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; @@ -304,7 +283,7 @@ class FlatStyle_RDM: public RetroshareDirModel uint64_t size; uint32_t mtime; uint64_t uploads; - bool hasUploads; + }; std::map m_cache;