// Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 #include "manager.h" #include "appstatisticsmonitortr.h" #include "chart.h" #include "idataprovider.h" #include #include #include #include #include #include #include using namespace ProjectExplorer; using namespace Utils; namespace AppStatisticsMonitor::Internal { class AppStatisticsMonitorView : public QWidget { public: explicit AppStatisticsMonitorView( AppStatisticsMonitorManager *appStatisticManager); ~AppStatisticsMonitorView() override; private: QComboBox *m_comboBox; std::unique_ptr m_chartMem; std::unique_ptr m_chartCpu; AppStatisticsMonitorManager *m_manager; }; AppStatisticsMonitorManager::AppStatisticsMonitorManager() { connect( ProjectExplorer::ProjectExplorerPlugin::instance(), &ProjectExplorer::ProjectExplorerPlugin::runControlStarted, this, [this](RunControl *runControl) { qint64 pid = runControl->applicationProcessHandle().pid(); m_pidNameMap[pid] = runControl->displayName(); m_rcPidMap[runControl] = pid; m_currentDataProvider = createDataProvider(pid); m_pidDataProviders.insert(pid, m_currentDataProvider); emit appStarted(runControl->displayName(), pid); }); connect( ProjectExplorer::ProjectExplorerPlugin::instance(), &ProjectExplorer::ProjectExplorerPlugin::runControlStoped, this, [this](RunControl *runControl) { const auto pidIt = m_rcPidMap.constFind(runControl); if (pidIt == m_rcPidMap.constEnd()) return; const qint64 pid = pidIt.value(); m_rcPidMap.erase(pidIt); m_pidNameMap.remove(pid); delete m_pidDataProviders[pid]; m_pidDataProviders.remove(pid); if (m_pidDataProviders.isEmpty()) setCurrentDataProvider(-1); else setCurrentDataProvider(m_pidDataProviders.keys().last()); emit appStoped(pid); }); } QString AppStatisticsMonitorManager::nameForPid(qint64 pid) const { const auto pidIt = m_pidNameMap.constFind(pid); if (pidIt == m_pidNameMap.constEnd()) return {}; return pidIt.value(); } IDataProvider *AppStatisticsMonitorManager::currentDataProvider() const { return m_currentDataProvider; } void AppStatisticsMonitorManager::setCurrentDataProvider(qint64 pid) { m_currentDataProvider = nullptr; const auto pidIt = m_pidDataProviders.constFind(pid); if (pidIt == m_pidDataProviders.constEnd()) return; m_currentDataProvider = pidIt.value(); connect( m_currentDataProvider, &IDataProvider::newDataAvailable, this, &AppStatisticsMonitorManager::newDataAvailable); } QHash AppStatisticsMonitorManager::pidNameMap() const { return m_pidNameMap; } // AppStatisticsMonitorView AppStatisticsMonitorView::AppStatisticsMonitorView(AppStatisticsMonitorManager *appManager) : m_manager(appManager) { auto layout = new QVBoxLayout; auto form = new QFormLayout; setLayout(layout); m_comboBox = new QComboBox(this); form->addRow(m_comboBox); m_chartMem = std::make_unique(Tr::tr("Memory consumption")); m_chartCpu = std::make_unique(Tr::tr("CPU consumption")); form->addRow(m_chartMem->chartView()); form->addRow(m_chartCpu->chartView()); layout->addLayout(form); for (auto pidName : m_manager->pidNameMap().asKeyValueRange()) { qint64 pid = pidName.first; m_comboBox->addItem(pidName.second + " : " + QString::number(pid), pid); } m_comboBox->setCurrentIndex(m_comboBox->count() - 1); m_chartCpu->clear(); m_chartMem->clear(); auto updateCharts = [this](int index) { m_manager->setCurrentDataProvider(m_comboBox->itemData(index).toLongLong()); if (m_manager->currentDataProvider() != nullptr) { const QList &memConsumptionHistory = m_manager->currentDataProvider()->memoryConsumptionHistory(); const QList &cpuConsumptionHistory = m_manager->currentDataProvider()->cpuConsumptionHistory(); m_chartMem->loadNewProcessData(memConsumptionHistory); m_chartCpu->loadNewProcessData(cpuConsumptionHistory); } }; if (m_comboBox->count() != 0) updateCharts(m_comboBox->currentIndex()); connect(m_comboBox, &QComboBox::currentIndexChanged, this, [updateCharts](int index) { updateCharts(index); }); connect( m_manager, &AppStatisticsMonitorManager::appStarted, this, [this](const QString &name, qint64 pid) { if (pid != m_comboBox->currentData()) { m_comboBox->addItem(name + " : " + QString::number(pid), pid); m_chartMem->clear(); m_chartCpu->clear(); m_comboBox->setCurrentIndex(m_comboBox->count() - 1); } }); connect(m_manager, &AppStatisticsMonitorManager::appStoped, this, [this](qint64 pid) { m_chartMem->addNewPoint({m_chartMem->lastPointX() + 1, 0}); m_chartCpu->addNewPoint({m_chartCpu->lastPointX() + 1, 0}); const int indx = m_comboBox->findData(pid); if (indx != -1) m_comboBox->removeItem(indx); }); connect(m_manager, &AppStatisticsMonitorManager::newDataAvailable, this, [this] { const IDataProvider *currentDataProvider = m_manager->currentDataProvider(); if (currentDataProvider != nullptr) { m_chartMem->addNewPoint( {(double) currentDataProvider->memoryConsumptionHistory().size(), currentDataProvider->memoryConsumptionLast()}); m_chartCpu->addNewPoint( {(double) currentDataProvider->cpuConsumptionHistory().size(), currentDataProvider->cpuConsumptionLast()}); } }); } AppStatisticsMonitorView::~AppStatisticsMonitorView() = default; // AppStatisticsMonitorViewFactory AppStatisticsMonitorViewFactory::AppStatisticsMonitorViewFactory( AppStatisticsMonitorManager *appStatisticManager) : m_manager(appStatisticManager) { setDisplayName(("AppStatisticsMonitor")); setPriority(300); setId("AppStatisticsMonitor"); setActivationSequence(QKeySequence("Alt+S")); } Core::NavigationView AppStatisticsMonitorViewFactory::createWidget() { return {new AppStatisticsMonitorView(m_manager), {}}; } } // namespace AppStatisticsMonitor::Internal