diff --git a/src/plugins/appstatisticsmonitor/CMakeLists.txt b/src/plugins/appstatisticsmonitor/CMakeLists.txt index 891da1f812a..292eb2a3eb2 100644 --- a/src/plugins/appstatisticsmonitor/CMakeLists.txt +++ b/src/plugins/appstatisticsmonitor/CMakeLists.txt @@ -1,4 +1,8 @@ +find_package(Qt6 COMPONENTS Charts QUIET) + add_qtc_plugin(AppStatisticsMonitor + CONDITION TARGET Qt6::Charts + DEPENDS Qt6::Charts SKIP_TRANSLATION PLUGIN_DEPENDS Core ProjectExplorer SOURCES diff --git a/src/plugins/appstatisticsmonitor/appstatisticsmonitor.qbs b/src/plugins/appstatisticsmonitor/appstatisticsmonitor.qbs index 3905a41a0aa..177dd9d0a28 100644 --- a/src/plugins/appstatisticsmonitor/appstatisticsmonitor.qbs +++ b/src/plugins/appstatisticsmonitor/appstatisticsmonitor.qbs @@ -3,6 +3,9 @@ QtcPlugin { Depends { name: "Core" } Depends { name: "ProjectExplorer" } + Depends { name: "Qt.charts"; required: false } + + condition: Qt.charts.present files: [ "appstatisticsmonitorplugin.cpp", diff --git a/src/plugins/appstatisticsmonitor/chart.cpp b/src/plugins/appstatisticsmonitor/chart.cpp index 2abf6d1ceb6..260282b39a4 100644 --- a/src/plugins/appstatisticsmonitor/chart.cpp +++ b/src/plugins/appstatisticsmonitor/chart.cpp @@ -5,11 +5,19 @@ #include +#include +#include +#include #include #include #include #include +#include +#include #include +#include + +using namespace Utils; namespace AppStatisticsMonitor::Internal { @@ -17,6 +25,100 @@ static const int padding = 40; static const int numPadding = 10; static const QRectF dataRangeDefault = QRectF(0, 0, 5, 1); +AppStatisticsMonitorChart::AppStatisticsMonitorChart( + const QString &name, QGraphicsItem *parent, Qt::WindowFlags wFlags) + : QChart(QChart::ChartTypeCartesian, parent, wFlags) + , m_series(new QLineSeries(this)) + , m_axisX(new QValueAxis()) + , m_axisY(new QValueAxis()) + , m_point(0, 0) + , m_chartView(new QChartView(this)) + , m_name(name) +{ + m_chartView->setMinimumHeight(200); + m_chartView->setMinimumWidth(400); + const QBrush brushTitle(creatorColor(Theme::Token_Text_Muted)); + const QBrush brush(creatorColor(Theme::Token_Background_Default)); + const QPen penBack(creatorColor(Theme::Token_Text_Muted)); + const QPen penAxis(creatorColor(Theme::Token_Text_Muted)); + + setTitleBrush(brushTitle); + setBackgroundBrush(brush); + setBackgroundPen(penBack); + m_axisX->setLinePen(penAxis); + m_axisY->setLinePen(penAxis); + m_axisX->setLabelsColor(creatorColor(Theme::Token_Text_Muted)); + m_axisY->setLabelsColor(creatorColor(Theme::Token_Text_Muted)); + QPen pen(creatorColor(Theme::Token_Accent_Default)); + pen.setWidth(2); + m_series->setPen(pen); + + setTitle(m_name + " " + QString::number(m_point.y(), 'g', 4) + "%"); + m_chartView->setRenderHint(QPainter::Antialiasing); + m_chartView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + addSeries(m_series); + + addAxis(m_axisX, Qt::AlignBottom); + addAxis(m_axisY, Qt::AlignLeft); + m_series->attachAxis(m_axisX); + m_series->attachAxis(m_axisY); + m_axisX->applyNiceNumbers(); + m_axisY->applyNiceNumbers(); + legend()->hide(); + + clear(); +} + +QChartView *AppStatisticsMonitorChart::chartView() +{ + return m_chartView; +} + +void AppStatisticsMonitorChart::addNewPoint(const QPointF &point) +{ + m_point = point; + if (m_axisY->max() < m_point.y()) + m_axisY->setRange(0, qRound(m_point.y()) + 1); + m_axisX->setRange(0, qRound(m_point.x()) + 1); + + setTitle(m_name + " " + QString::number(m_point.y(), 'g', 4) + "%"); + m_series->append(m_point); +} + +void AppStatisticsMonitorChart::loadNewProcessData(const QList &data) +{ + clear(); + QList points{{0, 0}}; + int i = 0; + double max_y = 0; + + for (double e : qAsConst(data)) { + points.push_back({double(++i), e}); + max_y = qMax(max_y, e); + } + + m_axisY->setRange(0, qRound(max_y) + 1); + m_axisX->setRange(0, data.size() + 1); + + m_series->clear(); + m_series->append(points); +} + +void AppStatisticsMonitorChart::clear() +{ + m_axisX->setRange(0, 5); + m_axisY->setRange(0, 1); + m_series->clear(); + m_series->append(0, 0); +} + +double AppStatisticsMonitorChart::lastPointX() const +{ + return m_point.x(); +} + +//---------------------- Chart ----------------------- + Chart::Chart(const QString &name, QWidget *parent) : QWidget(parent) , m_name(name) @@ -31,7 +133,7 @@ void Chart::addNewPoint(const QPointF &point) update(); } -void Chart::loadNewProcessData(QList data) +void Chart::loadNewProcessData(const QList &data) { clear(); for (long i = 0; i < data.size(); ++i) { @@ -59,7 +161,7 @@ void Chart::paintEvent(QPaintEvent *event) Q_UNUSED(event); QPainter painter(this); - painter.fillRect(rect(), Utils::creatorColor(Utils::Theme::Token_Background_Default)); + painter.fillRect(rect(), creatorColor(Theme::Token_Background_Default)); // add the name of the chart in the middle of the widget width and on the top painter.drawText( @@ -74,10 +176,10 @@ void Chart::paintEvent(QPaintEvent *event) double xPos = padding + (x - dataRange.left()) * m_xScale; if (xPos < padding || xPos > width() - padding) continue; - painter.setPen(Utils::creatorColor(Utils::Theme::Token_Foreground_Default)); + painter.setPen(creatorColor(Theme::Token_Foreground_Default)); painter.drawLine(xPos, padding, xPos, height() - padding); - painter.setPen(Utils::creatorColor(Utils::Theme::Token_Text_Muted)); + painter.setPen(creatorColor(Theme::Token_Text_Muted)); painter.drawText(xPos, height() - numPadding, QString::number(x)); } @@ -86,18 +188,18 @@ void Chart::paintEvent(QPaintEvent *event) if (yPos < padding || yPos > height() - padding) continue; - painter.setPen(Utils::creatorColor(Utils::Theme::Token_Foreground_Default)); + painter.setPen(creatorColor(Theme::Token_Foreground_Default)); painter.drawLine(padding, yPos, width() - padding, yPos); - painter.setPen(Utils::creatorColor(Utils::Theme::Token_Text_Muted)); + painter.setPen(creatorColor(Theme::Token_Text_Muted)); painter.drawText(numPadding, yPos, QString::number(y)); } - painter.setPen(Utils::creatorColor(Utils::Theme::Token_Foreground_Default)); + painter.setPen(creatorColor(Theme::Token_Foreground_Default)); painter.drawLine(padding, height() - padding, width() - padding, height() - padding); // X axis painter.drawLine(padding, height() - padding, padding, padding); // Y axis - QPen pen(Utils::creatorColor(Utils::Theme::Token_Accent_Default)); + QPen pen(creatorColor(Theme::Token_Accent_Default)); pen.setWidth(2); painter.setPen(pen); painter.setRenderHint(QPainter::Antialiasing); diff --git a/src/plugins/appstatisticsmonitor/chart.h b/src/plugins/appstatisticsmonitor/chart.h index 0a9ed927512..ed478061ce7 100644 --- a/src/plugins/appstatisticsmonitor/chart.h +++ b/src/plugins/appstatisticsmonitor/chart.h @@ -2,21 +2,51 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 #pragma once +#include #include #include #include #include #include +QT_BEGIN_NAMESPACE +class QChartView; +class QLineSeries; +class QValueAxis; +QT_END_NAMESPACE + namespace AppStatisticsMonitor::Internal { +class AppStatisticsMonitorChart : public QChart +{ +public: + AppStatisticsMonitorChart( + const QString &name, QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = {}); + + void addNewPoint(const QPointF &point); + void loadNewProcessData(const QList &data); + double lastPointX() const; + void clear(); + QChartView *chartView(); + +private: + QLineSeries *m_series; + QStringList m_titles; + QValueAxis *m_axisX; + QValueAxis *m_axisY; + QPointF m_point; + + QChartView *m_chartView; + QString m_name; +}; + class Chart : public QWidget { public: Chart(const QString &name, QWidget *parent = nullptr); void addNewPoint(const QPointF &point); - void loadNewProcessData(QList data); + void loadNewProcessData(const QList &data); double lastPointX() const; void clear(); diff --git a/src/plugins/appstatisticsmonitor/manager.cpp b/src/plugins/appstatisticsmonitor/manager.cpp index ad17b80dd78..a0a08fd36a0 100644 --- a/src/plugins/appstatisticsmonitor/manager.cpp +++ b/src/plugins/appstatisticsmonitor/manager.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -24,15 +25,15 @@ class AppStatisticsMonitorView : public QWidget { public: explicit AppStatisticsMonitorView( - AppStatisticsMonitorManager *appStatisticManager, QWidget *parent = nullptr); + AppStatisticsMonitorManager *appStatisticManager); ~AppStatisticsMonitorView() override; private: QComboBox *m_comboBox; - Chart *m_memChart; - Chart *m_cpuChart; + std::unique_ptr m_chartMem; + std::unique_ptr m_chartCpu; AppStatisticsMonitorManager *m_manager; }; @@ -114,25 +115,21 @@ QHash AppStatisticsMonitorManager::pidNameMap() const } // AppStatisticsMonitorView -AppStatisticsMonitorView::AppStatisticsMonitorView(AppStatisticsMonitorManager *dapManager, QWidget *) - : m_manager(dapManager) +AppStatisticsMonitorView::AppStatisticsMonitorView(AppStatisticsMonitorManager *appManager) + : m_manager(appManager) { auto layout = new QVBoxLayout; auto form = new QFormLayout; setLayout(layout); - m_comboBox = new QComboBox(); + m_comboBox = new QComboBox(this); form->addRow(m_comboBox); - m_memChart = new Chart("Memory consumption "); - m_memChart->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - m_memChart->clear(); - form->addRow(m_memChart); + m_chartMem = std::make_unique(tr("Memory consumption")); + m_chartCpu = std::make_unique(tr("CPU consumption")); - m_cpuChart = new Chart("CPU consumption "); - m_cpuChart->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - m_cpuChart->clear(); - form->addRow(m_cpuChart); + form->addRow(m_chartMem->chartView()); + form->addRow(m_chartCpu->chartView()); layout->addLayout(form); @@ -142,16 +139,19 @@ AppStatisticsMonitorView::AppStatisticsMonitorView(AppStatisticsMonitorManager * } m_comboBox->setCurrentIndex(m_comboBox->count() - 1); - m_memChart->clear(); - m_cpuChart->clear(); + m_chartCpu->clear(); + m_chartMem->clear(); auto updateCharts = [this](int index) { m_manager->setCurrentDataProvider(m_comboBox->itemData(index).toLongLong()); if (m_manager->currentDataProvider() != nullptr) { - m_memChart->loadNewProcessData( - m_manager->currentDataProvider()->memoryConsumptionHistory()); - m_cpuChart->loadNewProcessData( - m_manager->currentDataProvider()->cpuConsumptionHistory()); + const QList &memConsumptionHistory + = m_manager->currentDataProvider()->memoryConsumptionHistory(); + const QList &cpuConsumptionHistory + = m_manager->currentDataProvider()->cpuConsumptionHistory(); + + m_chartMem->loadNewProcessData(memConsumptionHistory); + m_chartCpu->loadNewProcessData(cpuConsumptionHistory); } }; @@ -170,16 +170,17 @@ AppStatisticsMonitorView::AppStatisticsMonitorView(AppStatisticsMonitorManager * if (pid != m_comboBox->currentData()) { m_comboBox->addItem(name + " : " + QString::number(pid), pid); - m_memChart->clear(); - m_cpuChart->clear(); + m_chartMem->clear(); + m_chartCpu->clear(); m_comboBox->setCurrentIndex(m_comboBox->count() - 1); } }); connect(m_manager, &AppStatisticsMonitorManager::appStoped, this, [this](qint64 pid) { - m_memChart->addNewPoint({m_memChart->lastPointX() + 1, 0}); - m_cpuChart->addNewPoint({m_cpuChart->lastPointX() + 1, 0}); + 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); @@ -188,10 +189,10 @@ AppStatisticsMonitorView::AppStatisticsMonitorView(AppStatisticsMonitorManager * connect(m_manager, &AppStatisticsMonitorManager::newDataAvailable, this, [this] { const IDataProvider *currentDataProvider = m_manager->currentDataProvider(); if (currentDataProvider != nullptr) { - m_memChart->addNewPoint( + m_chartMem->addNewPoint( {(double) currentDataProvider->memoryConsumptionHistory().size(), currentDataProvider->memoryConsumptionLast()}); - m_cpuChart->addNewPoint( + m_chartCpu->addNewPoint( {(double) currentDataProvider->cpuConsumptionHistory().size(), currentDataProvider->cpuConsumptionLast()}); }