/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include #include #include #include "OverallReplicaDetailView.hxx" #include #include #include "ReplicaChunkUsageDataContainers.h" #include "ReplicaDataAggregator.hxx" #include "ReplicaDataEvents.h" #include "ReplicaUsageDataContainers.h" #include "Source/Driller/DrillerMainWindowMessages.h" #include "Source/Driller/DrillerOperationTelemetryEvent.h" #include "Source/Driller/Replica/ReplicaDataView.hxx" #include "Source/Driller/Replica/ReplicaDisplayHelpers.h" #include "Source/Driller/Workspaces/Workspace.h" namespace Driller { //////////////////////// // TreeModelSavedState //////////////////////// class TreeModelSavedState : public AZ::UserSettings { public: AZ_RTTI(TreeModelSavedState, "{36103E46-2503-4EEE-BA4B-2650E25A5B26}", AZ::UserSettings); AZ_CLASS_ALLOCATOR(TreeModelSavedState, AZ::SystemAllocator, 0); AZStd::vector m_treeColumnStorage; static void Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serialize = azrtti_cast(context); if (serialize) { serialize->Class() ->Field("m_treeColumnStorage", &TreeModelSavedState::m_treeColumnStorage) ->Version(1); } } }; //////////////////////////////// // OverallReplicaTreeViewModel //////////////////////////////// OverallReplicaTreeViewModel::OverallReplicaTreeViewModel(AbstractOverallReplicaDetailView* overallDetailView) : BaseOverallTreeViewModel(overallDetailView) { } int OverallReplicaTreeViewModel::columnCount(const QModelIndex& parentIndex) const { (void)parentIndex; return CD_COUNT; } QVariant OverallReplicaTreeViewModel::data(const QModelIndex& index, int role) const { const bool relativeValue = true; const bool absoluteValue = false; const BaseDisplayHelper* baseDisplay = static_cast(index.internalPointer()); switch (index.column()) { case CD_DISPLAY_NAME: return displayNameData(baseDisplay, role); case CD_REPLICA_ID: { if (role == Qt::DisplayRole || role == Qt::UserRole) { AZ::u64 replicaId = 0; const BaseDisplayHelper* currentDisplay = baseDisplay; while (currentDisplay != nullptr && !azrtti_istypeof(currentDisplay)) { currentDisplay = currentDisplay->GetParent(); } if (currentDisplay) { const OverallReplicaDetailDisplayHelper* replicaDisplay = static_cast(currentDisplay); replicaId = replicaDisplay->GetReplicaId(); } if (role == Qt::DisplayRole) { return FormattingHelper::ReplicaID(replicaId); } else { return QVariant(replicaId); } } } break; case CD_TOTAL_SENT: return totalSentData(baseDisplay, role); case CD_AVG_SENT_FRAME: return avgSentPerFrameData(baseDisplay, role); case CD_AVG_SENT_SECOND: return avgSentPerSecondData(baseDisplay, role); case CD_PARENT_PERCENT_SENT: return percentOfSentData(baseDisplay, role, relativeValue); case CD_TOTAL_PERCENT_SENT: return percentOfSentData(baseDisplay, role, absoluteValue); case CD_TOTAL_RECEIVED: return totalReceivedData(baseDisplay, role); case CD_AVG_RECEIVED_FRAME: return avgReceivedPerFrameData(baseDisplay, role); case CD_AVG_RECEIVED_SECOND: return avgReceivedPerSecondData(baseDisplay, role); case CD_PARENT_PERCENT_RECEIVED: return percentOfReceivedData(baseDisplay, role, relativeValue); case CD_TOTAL_PERCENT_RECEIVED: return percentOfReceivedData(baseDisplay, role, absoluteValue); default: AZ_Warning("OverallReplicaTreeViewModel", false, "Unknown Column"); break; } return QVariant(); } QVariant OverallReplicaTreeViewModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole) { if (orientation == Qt::Horizontal) { switch (section) { case CD_DISPLAY_NAME: return QString("Name"); case CD_REPLICA_ID: return QString("ReplicaId"); case CD_TOTAL_SENT: return QString("Sent Bytes"); case CD_AVG_SENT_FRAME: return QString("Sent Bytes/Frame"); case CD_AVG_SENT_SECOND: return QString("Sent Bytes/Second"); case CD_PARENT_PERCENT_SENT: return QString("% of Parent Sent"); case CD_TOTAL_PERCENT_SENT: return QString("% of Total Sent"); case CD_TOTAL_RECEIVED: return QString("Received Bytes"); case CD_AVG_RECEIVED_FRAME: return QString("Received Bytes/Frame"); case CD_AVG_RECEIVED_SECOND: return QString("Received Bytes/Second"); case CD_PARENT_PERCENT_RECEIVED: return QString("% of Parent Received"); case CD_TOTAL_PERCENT_RECEIVED: return QString("% of Total Received"); } } } return QVariant(); } const BaseDisplayHelper* OverallReplicaTreeViewModel::FindDisplayHelperAtRoot(int row) const { if (row < 0 || row >= m_tableViewOrdering.size()) { return nullptr; } return m_overallReplicaDetailView->FindReplicaDisplayHelper(m_tableViewOrdering[row]); } ///////////////////////////////////////// // OverallReplicaChunkTypeTreeViewModel ///////////////////////////////////////// OverallReplicaChunkTypeTreeViewModel::OverallReplicaChunkTypeTreeViewModel(AbstractOverallReplicaDetailView* overallDetailView) : BaseOverallTreeViewModel(overallDetailView) { } int OverallReplicaChunkTypeTreeViewModel::columnCount(const QModelIndex& parentIndex) const { (void)parentIndex; return CD_COUNT; } QVariant OverallReplicaChunkTypeTreeViewModel::data(const QModelIndex& index, int role) const { const bool relativeValue = true; const bool absoluteValue = false; const BaseDisplayHelper* baseDisplay = static_cast(index.internalPointer()); switch (index.column()) { case CD_DISPLAY_NAME: return displayNameData(baseDisplay, role); case CD_TOTAL_SENT: return totalSentData(baseDisplay, role); case CD_AVG_SENT_FRAME: return avgSentPerFrameData(baseDisplay, role); case CD_AVG_SENT_SECOND: return avgSentPerSecondData(baseDisplay, role); case CD_PARENT_PERCENT_SENT: return percentOfSentData(baseDisplay, role, relativeValue); case CD_TOTAL_PERCENT_SENT: return percentOfSentData(baseDisplay, role, absoluteValue); case CD_TOTAL_RECEIVED: return totalReceivedData(baseDisplay, role); case CD_AVG_RECEIVED_FRAME: return avgReceivedPerFrameData(baseDisplay, role); case CD_AVG_RECEIVED_SECOND: return avgReceivedPerSecondData(baseDisplay, role); case CD_PARENT_PERCENT_RECEIVED: return percentOfReceivedData(baseDisplay, role, relativeValue); case CD_TOTAL_PERCENT_RECEIVED: return percentOfReceivedData(baseDisplay, role, absoluteValue); default: AZ_Warning("OverallReplicaTreeViewModel", false, "Unknown Column"); break; } return QVariant(); } QVariant OverallReplicaChunkTypeTreeViewModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole) { if (orientation == Qt::Horizontal) { switch (section) { case CD_DISPLAY_NAME: return QString("Name"); case CD_TOTAL_SENT: return QString("Sent Bytes"); case CD_AVG_SENT_FRAME: return QString("Sent Bytes/Frame"); case CD_AVG_SENT_SECOND: return QString("Sent Bytes/Second"); case CD_PARENT_PERCENT_SENT: return QString("% of Parent Sent"); case CD_TOTAL_PERCENT_SENT: return QString("% of Total Sent"); case CD_TOTAL_RECEIVED: return QString("Received Bytes"); case CD_AVG_RECEIVED_FRAME: return QString("Received Bytes/Frame"); case CD_AVG_RECEIVED_SECOND: return QString("Received Bytes/Second"); case CD_PARENT_PERCENT_RECEIVED: return QString("% of Parent Received"); case CD_TOTAL_PERCENT_RECEIVED: return QString("% of Total Received"); } } } return QVariant(); } const BaseDisplayHelper* OverallReplicaChunkTypeTreeViewModel::FindDisplayHelperAtRoot(int row) const { if (row < 0 || row >= m_tableViewOrdering.size()) { return nullptr; } return m_overallReplicaDetailView->FindReplicaChunkTypeDisplayHelper(m_tableViewOrdering[row]); } ///////////////////////////// // OverallReplicaDetailView ///////////////////////////// const char* OverallReplicaDetailView::WINDOW_STATE_FORMAT = "OVERALL_REPLICA_DETAIL_VIEW_WINDOW_STATE"; const char* OverallReplicaDetailView::REPLICA_TREE_STATE_FORMAT = "OVERALL_REPLICA_DETAIL_VIEW_TREE_STATE"; const char* OverallReplicaDetailView::REPLICA_CHUNK_TREE_STATE_FORMAT = "OVERALL_REPLICA_CHUNK_DETAIL_VIEW_TREE_STATE"; OverallReplicaDetailView::OverallReplicaDetailView(ReplicaDataView* dataView, const ReplicaDataAggregator& dataAggregator) : AbstractOverallReplicaDetailView() , m_lifespanTelemetry("OverallReplicaDetailView") , m_replicaDataView(dataView) , m_windowStateCRC(AZ::Crc32(WINDOW_STATE_FORMAT)) , m_replicaTreeStateCRC(AZ::Crc32(REPLICA_TREE_STATE_FORMAT)) , m_replicaChunkTreeStateCRC(AZ::Crc32(REPLICA_CHUNK_TREE_STATE_FORMAT)) , m_dataAggregator(dataAggregator) , m_overallReplicaModel(this) , m_replicaFilterProxyModel(this) , m_overallChunkTypeModel(this) , m_replicaChunkTypeFilterProxyModel(this) { setAttribute(Qt::WA_DeleteOnClose, true); setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint); m_gui = azcreate(Ui::OverallReplicaDetailView, ()); m_gui->setupUi(this); show(); raise(); activateWindow(); setFocus(); QString titleName("Overall Replica Usage - %2"); this->setWindowTitle(titleName.arg(m_dataAggregator.GetInspectionFileName())); // Loading up saved state AZStd::intrusive_ptr windowState = AZ::UserSettings::Find(m_windowStateCRC, AZ::UserSettings::CT_GLOBAL); if (windowState) { windowState->RestoreGeometry(this); } auto treeState = AZ::UserSettings::Find(m_replicaTreeStateCRC, AZ::UserSettings::CT_GLOBAL); if (treeState) { QByteArray treeData((const char*)treeState->m_treeColumnStorage.data(), (int)treeState->m_treeColumnStorage.size()); m_gui->overallReplicaUsage->header()->restoreState(treeData); } treeState = AZ::UserSettings::Find(m_replicaChunkTreeStateCRC, AZ::UserSettings::CT_GLOBAL); if (treeState) { QByteArray treeData((const char*)treeState->m_treeColumnStorage.data(), (int)treeState->m_treeColumnStorage.size()); m_gui->overallChunkTypeUsage->header()->restoreState(treeData); } m_gui->startFrame->setMinimum(0); m_gui->startFrame->setValue(0); m_gui->endFrame->setMaximum(static_cast(m_dataAggregator.GetFrameCount()) - 1); m_gui->endFrame->setValue(static_cast(m_dataAggregator.GetFrameCount() - 1)); m_changeTimer.setInterval(500); m_changeTimer.setSingleShot(true); UpdateFrameBoundaries(); ParseData(); SetupTreeView(); UpdateDisplay(); QObject::connect(m_gui->startFrame, SIGNAL(valueChanged(int)), this, SLOT(QueueUpdate(int))); QObject::connect(m_gui->endFrame, SIGNAL(valueChanged(int)), this, SLOT(QueueUpdate(int))); QObject::connect(m_gui->framesPerSecond, SIGNAL(valueChanged(int)),this,SLOT(OnFPSChanged(int))); connect(&m_changeTimer, SIGNAL(timeout()), SLOT(OnDataRangeChanged())); } OverallReplicaDetailView::~OverallReplicaDetailView() { ClearData(); // Save out whatever data we want to save out. auto pState = AZ::UserSettings::CreateFind(m_windowStateCRC, AZ::UserSettings::CT_GLOBAL); if (pState) { pState->CaptureGeometry(this); } auto treeState = AZ::UserSettings::CreateFind(m_replicaTreeStateCRC, AZ::UserSettings::CT_GLOBAL); if (treeState) { if (m_gui->overallReplicaUsage && m_gui->overallReplicaUsage->header()) { QByteArray qba = m_gui->overallReplicaUsage->header()->saveState(); treeState->m_treeColumnStorage.assign((AZ::u8*)qba.begin(), (AZ::u8*)qba.end()); } } treeState = AZ::UserSettings::CreateFind(m_replicaChunkTreeStateCRC, AZ::UserSettings::CT_GLOBAL); if (treeState) { if (m_gui->overallChunkTypeUsage && m_gui->overallChunkTypeUsage->header()) { QByteArray qba = m_gui->overallChunkTypeUsage->header()->saveState(); treeState->m_treeColumnStorage.assign((AZ::u8*)qba.begin(), (AZ::u8*)qba.end()); } } if (m_replicaDataView) { m_replicaDataView->SignalDialogClosed(this); } azdestroy(m_gui); } int OverallReplicaDetailView::GetFrameRange() const { return m_frameRange; } int OverallReplicaDetailView::GetFPS() const { return m_gui->framesPerSecond->value(); } void OverallReplicaDetailView::SignalDataViewDestroyed(ReplicaDataView* replicaDataView) { if (m_replicaDataView == replicaDataView) { m_replicaDataView = nullptr; } close(); } void OverallReplicaDetailView::ApplySettingsFromWorkspace(WorkspaceSettingsProvider*) { } void OverallReplicaDetailView::ActivateWorkspaceSettings(WorkspaceSettingsProvider*) { } void OverallReplicaDetailView::SaveSettingsToWorkspace(WorkspaceSettingsProvider*) { } void OverallReplicaDetailView::ApplyPersistentState() { } void OverallReplicaDetailView::Reflect(AZ::ReflectContext* context) { (void)context; } void OverallReplicaDetailView::OnFPSChanged(int fps) { (void)fps; UpdateDisplay(); } void OverallReplicaDetailView::QueueUpdate(int ignoredFrame) { (void)ignoredFrame; m_changeTimer.start(); } void OverallReplicaDetailView::OnDataRangeChanged() { ParseData(); UpdateFrameBoundaries(); UpdateDisplay(); } OverallReplicaDetailDisplayHelper* OverallReplicaDetailView::CreateReplicaDisplayHelper(const char* replicaName, AZ::u64 replicaId) { OverallReplicaDetailDisplayHelper* detailDisplay = nullptr; ReplicaDisplayHelperMap::iterator displayIter = m_replicaDisplayHelpers.find(replicaId); if (displayIter == m_replicaDisplayHelpers.end()) { detailDisplay = aznew OverallReplicaDetailDisplayHelper(replicaName, replicaId); m_replicaDisplayHelpers.insert(ReplicaDisplayHelperMap::value_type(replicaId, detailDisplay)); m_overallReplicaModel.m_tableViewOrdering.push_back(replicaId); } else { detailDisplay = displayIter->second; } return detailDisplay; } OverallReplicaDetailDisplayHelper* OverallReplicaDetailView::FindReplicaDisplayHelper(AZ::u64 replicaId) { OverallReplicaDetailDisplayHelper* detailDisplay = nullptr; ReplicaDisplayHelperMap::iterator displayIter = m_replicaDisplayHelpers.find(replicaId); if (displayIter != m_replicaDisplayHelpers.end()) { detailDisplay = displayIter->second; } return detailDisplay; } ReplicaChunkDetailDisplayHelper* OverallReplicaDetailView::CreateReplicaChunkTypeDisplayHelper(const AZStd::string& chunkTypeName, AZ::u32 chunkIndex) { ReplicaChunkDetailDisplayHelper* detailDisplay = nullptr; ReplicaChunkTypeDisplayHelperMap::iterator displayIter = m_replicaChunkTypeDisplayHelpers.find(chunkTypeName); if (displayIter == m_replicaChunkTypeDisplayHelpers.end()) { detailDisplay = aznew ReplicaChunkDetailDisplayHelper(chunkTypeName.c_str(), chunkIndex); m_replicaChunkTypeDisplayHelpers.insert(ReplicaChunkTypeDisplayHelperMap::value_type(chunkTypeName, detailDisplay)); m_overallChunkTypeModel.m_tableViewOrdering.push_back(chunkTypeName); } else { detailDisplay = displayIter->second; } return detailDisplay; } ReplicaChunkDetailDisplayHelper* OverallReplicaDetailView::FindReplicaChunkTypeDisplayHelper(const AZStd::string& chunkTypeName) { ReplicaChunkDetailDisplayHelper* detailDisplay = nullptr; ReplicaChunkTypeDisplayHelperMap::iterator displayIter = m_replicaChunkTypeDisplayHelpers.find(chunkTypeName); if (displayIter != m_replicaChunkTypeDisplayHelpers.end()) { detailDisplay = displayIter->second; } return detailDisplay; } void OverallReplicaDetailView::SaveOnExit() { } void OverallReplicaDetailView::UpdateFrameBoundaries() { m_gui->startFrame->setMaximum(m_gui->endFrame->value()); m_gui->endFrame->setMinimum(m_gui->startFrame->value()); m_frameRange = (m_gui->endFrame->value() - m_gui->startFrame->value()) + 1; if (m_frameRange <= 0) { m_frameRange = 1; } } void OverallReplicaDetailView::ParseData() { // Not the best approach. But this shouldn't update all that frequently. ClearData(); FrameNumberType startFrame = static_cast(m_gui->startFrame->value()); FrameNumberType endFrame = static_cast(m_gui->endFrame->value()); EventNumberType startIndex = m_dataAggregator.GetFirstIndexAtFrame(startFrame); EventNumberType endIndex = m_dataAggregator.GetFirstIndexAtFrame(endFrame) + m_dataAggregator.NumOfEventsAtFrame(endFrame); const Aggregator::EventListType& events = m_dataAggregator.GetEvents(); for (EventNumberType currentIndex = startIndex; currentIndex < endIndex; ++currentIndex) { ReplicaChunkEvent* chunkEvent = static_cast(events[currentIndex]); // Since I process each event twice, I need to do the total aggregation seperately. if (chunkEvent->GetEventType() == Replica::RET_CHUNK_DATASET_SENT || chunkEvent->GetEventType() == Replica::RET_CHUNK_RPC_SENT) { m_totalUsageAggregator.m_bytesSent += chunkEvent->GetUsageBytes(); } else { m_totalUsageAggregator.m_bytesReceived += chunkEvent->GetUsageBytes(); } ProcessForReplica(chunkEvent); ProcessForReplicaChunk(chunkEvent); } } void OverallReplicaDetailView::ProcessForReplica(ReplicaChunkEvent* chunkEvent) { const char* replicaName = chunkEvent->GetReplicaName(); AZ::u64 replicaId = chunkEvent->GetReplicaId(); OverallReplicaDetailDisplayHelper* replicaDisplayHelper = CreateReplicaDisplayHelper(replicaName, replicaId); if (replicaDisplayHelper) { if (chunkEvent->GetEventType() == Replica::RET_CHUNK_DATASET_SENT || chunkEvent->GetEventType() == Replica::RET_CHUNK_RPC_SENT) { replicaDisplayHelper->m_bandwidthUsageAggregator.m_bytesSent += chunkEvent->GetUsageBytes(); } else if (chunkEvent->GetEventType() == Replica::RET_CHUNK_RPC_RECEIVED || chunkEvent->GetEventType() == Replica::RET_CHUNK_DATASET_RECEIVED) { replicaDisplayHelper->m_bandwidthUsageAggregator.m_bytesReceived += chunkEvent->GetUsageBytes(); } ReplicaChunkDetailDisplayHelper* chunkDetailDisplayHelper = replicaDisplayHelper->FindReplicaChunk(chunkEvent->GetReplicaChunkIndex()); if (chunkDetailDisplayHelper == nullptr) { chunkDetailDisplayHelper = replicaDisplayHelper->CreateReplicaChunkDisplayHelper(chunkEvent->GetChunkTypeName(), chunkEvent->GetReplicaChunkIndex()); } ProcessForBaseDetailDisplayHelper(chunkEvent, chunkDetailDisplayHelper); } } void OverallReplicaDetailView::ProcessForReplicaChunk(ReplicaChunkEvent* chunkEvent) { AZ::u32 chunkId = chunkEvent->GetReplicaChunkIndex(); AZStd::string chunkTypeName = chunkEvent->GetChunkTypeName(); ReplicaChunkDetailDisplayHelper* chunkDisplayHelper = CreateReplicaChunkTypeDisplayHelper(chunkTypeName, chunkId); if (chunkDisplayHelper) { ProcessForBaseDetailDisplayHelper(chunkEvent, chunkDisplayHelper); } } void OverallReplicaDetailView::ProcessForBaseDetailDisplayHelper(ReplicaChunkEvent* chunkEvent, BaseDetailDisplayHelper* detailDisplayHelper) { if (chunkEvent->GetEventType() == Replica::RET_CHUNK_DATASET_SENT || chunkEvent->GetEventType() == Replica::RET_CHUNK_DATASET_RECEIVED) { ReplicaChunkDataSetEvent* dataSetEvent = static_cast(chunkEvent); detailDisplayHelper->SetupDataSet(dataSetEvent->GetIndex(), dataSetEvent->GetDataSetName()); DataSetDisplayFilter* dataSetDisplayFilter = detailDisplayHelper->GetDataSetDisplayHelper(); DataSetDisplayHelper* dataSetDisplayHelper = detailDisplayHelper->FindDataSet(dataSetEvent->GetIndex()); if (chunkEvent->GetEventType() == Replica::RET_CHUNK_DATASET_SENT) { detailDisplayHelper->m_bandwidthUsageAggregator.m_bytesSent += chunkEvent->GetUsageBytes(); dataSetDisplayFilter->m_bandwidthUsageAggregator.m_bytesSent += chunkEvent->GetUsageBytes(); dataSetDisplayHelper->m_bandwidthUsageAggregator.m_bytesSent += chunkEvent->GetUsageBytes(); } else { detailDisplayHelper->m_bandwidthUsageAggregator.m_bytesReceived += chunkEvent->GetUsageBytes(); dataSetDisplayFilter->m_bandwidthUsageAggregator.m_bytesReceived += chunkEvent->GetUsageBytes(); dataSetDisplayHelper->m_bandwidthUsageAggregator.m_bytesReceived += chunkEvent->GetUsageBytes(); } } else { ReplicaChunkRPCEvent* rpcEvent = static_cast(chunkEvent); detailDisplayHelper->SetupRPC(rpcEvent->GetIndex(), rpcEvent->GetRPCName()); RPCDisplayFilter* rpcDisplayFilter = detailDisplayHelper->GetRPCDisplayHelper(); RPCDisplayHelper* rpcDisplayHelper = detailDisplayHelper->FindRPC(rpcEvent->GetIndex()); if (chunkEvent->GetEventType() == Replica::RET_CHUNK_RPC_SENT) { detailDisplayHelper->m_bandwidthUsageAggregator.m_bytesSent += chunkEvent->GetUsageBytes(); rpcDisplayFilter->m_bandwidthUsageAggregator.m_bytesSent += chunkEvent->GetUsageBytes(); rpcDisplayHelper->m_bandwidthUsageAggregator.m_bytesSent += chunkEvent->GetUsageBytes(); } else { detailDisplayHelper->m_bandwidthUsageAggregator.m_bytesReceived += chunkEvent->GetUsageBytes(); rpcDisplayFilter->m_bandwidthUsageAggregator.m_bytesReceived += chunkEvent->GetUsageBytes(); rpcDisplayHelper->m_bandwidthUsageAggregator.m_bytesReceived += chunkEvent->GetUsageBytes(); } } } void OverallReplicaDetailView::ClearData() { for (auto& mapPair : m_replicaDisplayHelpers) { delete mapPair.second; } m_replicaDisplayHelpers.clear(); m_overallReplicaModel.m_tableViewOrdering.clear(); for (auto& mapPair : m_replicaChunkTypeDisplayHelpers) { delete mapPair.second; } m_replicaChunkTypeDisplayHelpers.clear(); m_overallChunkTypeModel.m_tableViewOrdering.clear(); m_totalUsageAggregator.m_bytesSent = 0; m_totalUsageAggregator.m_bytesReceived = 0; } void OverallReplicaDetailView::UpdateDisplay() { int frameRange = GetFrameRange(); // Sent Total m_gui->totalBytesSent->setText(QString::number(m_totalUsageAggregator.m_bytesSent)); size_t avgBytesPerFrame = m_totalUsageAggregator.m_bytesSent / frameRange; m_gui->avgBytesSentFrame->setText(QString::number(avgBytesPerFrame)); m_gui->avgBytesSentSecond->setText(QString::number(avgBytesPerFrame * GetFPS())); // Received Total m_gui->totalBytesReceived->setText(QString::number(m_totalUsageAggregator.m_bytesReceived)); avgBytesPerFrame = m_totalUsageAggregator.m_bytesReceived / frameRange; m_gui->avgBytesReceivedFrame->setText(QString::number(avgBytesPerFrame)); m_gui->avgBytesReceivedSecond->setText(QString::number(avgBytesPerFrame * GetFPS())); m_overallChunkTypeModel.layoutChanged(); m_overallReplicaModel.layoutChanged(); } void OverallReplicaDetailView::SetupTreeView() { SetupReplicaTreeView(); SetupReplicaChunkTypeTreeView(); } void OverallReplicaDetailView::SetupReplicaTreeView() { m_replicaFilterProxyModel.setSortRole(Qt::UserRole); m_replicaFilterProxyModel.setSourceModel(&m_overallReplicaModel); m_gui->overallReplicaUsage->setModel(&m_replicaFilterProxyModel); } void OverallReplicaDetailView::SetupReplicaChunkTypeTreeView() { m_replicaChunkTypeFilterProxyModel.setSortRole(Qt::UserRole); m_replicaChunkTypeFilterProxyModel.setSourceModel(&m_overallChunkTypeModel); m_gui->overallChunkTypeUsage->setModel(&m_replicaChunkTypeFilterProxyModel); } };