VirtualBox

Ignore:
Timestamp:
Aug 21, 2019 7:25:25 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
132846
Message:

FE/Qt: bugref:9510: Merging 'Performance Monitor' and 'Runtime Information' tabs

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
2 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r80379 r80381  
    736736        src/runtime/information/UIInformationRuntime.h \
    737737        src/runtime/information/UIInformationView.h \
    738         src/runtime/information/UIPerformanceMonitor.h \
    739738        src/runtime/information/UIVMInformationDialog.h \
    740739        src/guestctrl/UIFileManager.h \
     
    978977        src/runtime/UIFrameBuffer.cpp \
    979978        src/runtime/UIIndicatorsPool.cpp \
    980         src/runtime/information/UIPerformanceMonitor.cpp \
     979        src/runtime/information/UIInformationRuntime.cpp \
    981980        src/guestctrl/UIFileManager.cpp \
    982981        src/guestctrl/UIFileManagerLogPanel.cpp \
     
    12031202        src/runtime/information/UIInformationRuntime.cpp \
    12041203        src/runtime/information/UIInformationView.cpp \
    1205         src/runtime/information/UIPerformanceMonitor.cpp \
    12061204        src/runtime/information/UIVMInformationDialog.cpp \
    12071205        src/guestctrl/UIFileManager.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIInformationRuntime.cpp

    r80379 r80381  
    1818/* Qt includes: */
    1919#include <QApplication>
    20 #include <QTableWidget>
    21 #include <QTextDocument>
    22 #include <QVBoxLayout>
     20#include <QLabel>
     21#include <QPainter>
     22#include <QGridLayout>
     23#include <QStyle>
     24#include <QTimer>
    2325
    2426/* GUI includes: */
    2527#include "UICommon.h"
    2628#include "UIConverter.h"
    27 #include "UIIconPool.h"
     29#include "UIExtraDataManager.h"
    2830#include "UIInformationRuntime.h"
    29 #include "UIInformationDataItem.h"
    30 #include "UIInformationItem.h"
    31 #include "UIInformationView.h"
    32 #include "UIExtraDataManager.h"
    33 #include "UIInformationModel.h"
    34 
    35 /* COM includes: */
    36 #include "CDisplay.h"
     31#include "UISession.h"
     32
    3733#include "CGuest.h"
    38 #include "CMachineDebugger.h"
     34#include "CPerformanceCollector.h"
     35#include "CPerformanceMetric.h"
    3936#include "CVRDEServerInfo.h"
    4037
    41 UIInformationRuntime::UIInformationRuntime(QWidget *pParent, const CMachine &machine, const CConsole &console)
     38#define DATA_SERIES_SIZE 2
     39const ULONG iPeriod = 1;
     40const int iMaximumQueueSize = 120;
     41const int iMetricSetupCount = 1;
     42const int iDecimalCount = 2;
     43
     44/*********************************************************************************************************************************
     45*   UIChart definition.                                                                                     *
     46*********************************************************************************************************************************/
     47
     48class UIChart : public QWidget
     49{
     50
     51    Q_OBJECT;
     52
     53public:
     54
     55    UIChart(QWidget *pParent, const UISubMetric *pSubMetric);
     56    void setFontSize(int iFontSize);
     57    int  fontSize() const;
     58    void setTextList(const QStringList &textList);
     59    const QStringList &textList() const;
     60
     61    bool drawPieChart() const;
     62    void setDrawPieChart(bool fDrawPieChart);
     63
     64    bool useGradientLineColor() const;
     65    void setUseGradientLineColor(bool fUseGradintLineColor);
     66
     67    QColor dataSeriesColor(int iDataSeriesIndex);
     68    void setDataSeriesColor(int iDataSeriesIndex, const QColor &color);
     69
     70    QString XAxisLabel();
     71    void setXAxisLabel(const QString &strLabel);
     72
     73protected:
     74
     75    virtual void paintEvent(QPaintEvent *pEvent) /* override */;
     76    virtual QSize minimumSizeHint() const /* override */;
     77    virtual QSize sizeHint() const  /* override */;
     78
     79private:
     80
     81    virtual void computeFontSize();
     82    void drawXAxisLabels(QPainter &painter, int iXSubAxisCount);
     83    void drawPieCharts(QPainter &painter, ULONG iMaximum);
     84
     85    const UISubMetric *m_pSubMetric;
     86    QSize m_size;
     87    QFont m_font;
     88    int m_iMarginLeft;
     89    int m_iMarginRight;
     90    int m_iMarginTop;
     91    int m_iMarginBottom;
     92    QStringList m_textList;
     93    int m_iPieChartSize;
     94    QRect m_pieChartRect[DATA_SERIES_SIZE];
     95    bool m_fDrawPieChart;
     96    bool m_fUseGradientLineColor;
     97    QColor m_dataSeriesColor[DATA_SERIES_SIZE];
     98    QString m_strXAxisLabel;
     99};
     100
     101
     102/*********************************************************************************************************************************
     103*   UIChart implementation.                                                                                     *
     104*********************************************************************************************************************************/
     105
     106UIChart::UIChart(QWidget *pParent, const UISubMetric *pSubMetric)
     107    :QWidget(pParent)
     108    , m_pSubMetric(pSubMetric)
     109    , m_size(QSize(50, 50))
     110    , m_fDrawPieChart(true)
     111    , m_fUseGradientLineColor(true)
     112{
     113    m_dataSeriesColor[0] = QColor(Qt::red);
     114    m_dataSeriesColor[1] = QColor(Qt::blue);
     115
     116    m_iMarginLeft = 1 * qApp->QApplication::style()->pixelMetric(QStyle::PM_LayoutTopMargin);
     117    m_iMarginRight = 6 * qApp->QApplication::style()->pixelMetric(QStyle::PM_LayoutTopMargin);
     118    m_iMarginTop = 0.3 * qApp->QApplication::style()->pixelMetric(QStyle::PM_LayoutTopMargin);
     119    m_iMarginBottom = 2 * qApp->QApplication::style()->pixelMetric(QStyle::PM_LayoutTopMargin);
     120    m_iPieChartSize = 1.5f * qApp->style()->pixelMetric(QStyle::PM_LargeIconSize);
     121    m_pieChartRect[0] = QRect(1.5 * m_iMarginLeft, 1.5 * m_iMarginTop, m_iPieChartSize, m_iPieChartSize);
     122    m_pieChartRect[1] = QRect(m_pieChartRect[0].x() + m_iPieChartSize + 0.5 * m_iMarginLeft, 1.5 * m_iMarginTop, m_iPieChartSize, m_iPieChartSize);
     123    m_size = QSize(6 * m_iPieChartSize, 2 * m_iPieChartSize);
     124}
     125
     126void UIChart::setFontSize(int iFontSize)
     127{
     128    m_font.setPixelSize(iFontSize);
     129}
     130
     131int UIChart::fontSize() const
     132{
     133    return m_font.pixelSize();
     134}
     135
     136void UIChart::setTextList(const QStringList &textList)
     137{
     138    m_textList = textList;
     139    computeFontSize();
     140}
     141
     142const QStringList &UIChart::textList() const
     143{
     144    return m_textList;
     145}
     146
     147bool UIChart::drawPieChart() const
     148{
     149    return m_fDrawPieChart;
     150}
     151
     152void UIChart::setDrawPieChart(bool fDrawPieChart)
     153{
     154    if (m_fDrawPieChart == fDrawPieChart)
     155        return;
     156    m_fDrawPieChart = fDrawPieChart;
     157    update();
     158}
     159
     160bool UIChart::useGradientLineColor() const
     161{
     162    return m_fUseGradientLineColor;
     163}
     164
     165void UIChart::setUseGradientLineColor(bool fUseGradintLineColor)
     166{
     167    if (m_fUseGradientLineColor == fUseGradintLineColor)
     168        return;
     169    m_fUseGradientLineColor = fUseGradintLineColor;
     170    update();
     171}
     172
     173
     174QColor UIChart::dataSeriesColor(int iDataSeriesIndex)
     175{
     176    if (iDataSeriesIndex >= DATA_SERIES_SIZE)
     177        return QColor();
     178    return m_dataSeriesColor[iDataSeriesIndex];
     179}
     180
     181void UIChart::setDataSeriesColor(int iDataSeriesIndex, const QColor &color)
     182{
     183    if (iDataSeriesIndex >= DATA_SERIES_SIZE)
     184        return;
     185    if (m_dataSeriesColor[iDataSeriesIndex] == color)
     186        return;
     187    m_dataSeriesColor[iDataSeriesIndex] = color;
     188    update();
     189}
     190
     191QString UIChart::XAxisLabel()
     192{
     193    return m_strXAxisLabel;
     194}
     195
     196void UIChart::setXAxisLabel(const QString &strLabel)
     197{
     198    m_strXAxisLabel = strLabel;
     199}
     200
     201QSize UIChart::minimumSizeHint() const
     202{
     203    return m_size;
     204}
     205
     206QSize UIChart::sizeHint() const
     207{
     208    return m_size;
     209}
     210
     211void UIChart::computeFontSize()
     212{
     213    int iFontSize = 24;
     214
     215    //const QString &strText = m_pSubMetric->name();
     216    foreach (const QString &strText, m_textList)
     217    {
     218        m_font.setPixelSize(iFontSize);
     219
     220        do{
     221            int iWidth = QFontMetrics(m_font).width(strText);
     222            if (iWidth + m_iMarginLeft + m_iMarginRight > m_size.width())
     223                --iFontSize;
     224            else
     225                break;
     226            m_font.setPixelSize(iFontSize);
     227        }while(iFontSize > 1);
     228    }
     229}
     230
     231void UIChart::paintEvent(QPaintEvent *pEvent)
     232{
     233    Q_UNUSED(pEvent);
     234    QPainter painter(this);
     235    painter.setRenderHint(QPainter::Antialiasing);
     236
     237    /* Draw a rectanglar grid over which we will draw the line graphs: */
     238    int iChartHeight = height() - (m_iMarginTop + m_iMarginBottom);
     239    int iChartWidth = width() - (m_iMarginLeft + m_iMarginRight);
     240    QColor mainAxisColor(120, 120, 120);
     241    QColor subAxisColor(200, 200, 200);
     242    /* Draw the main axes: */
     243    painter.setPen(mainAxisColor);
     244    painter.drawRect(QRect(m_iMarginLeft, m_iMarginTop, iChartWidth, iChartHeight));
     245
     246    /* draw Y subaxes: */
     247    painter.setPen(subAxisColor);
     248    int iYSubAxisCount = 3;
     249    for (int i = 0; i < iYSubAxisCount; ++i)
     250    {
     251        float fSubAxisY = m_iMarginTop + (i + 1) * iChartHeight / (float) (iYSubAxisCount + 1);
     252        painter.drawLine(m_iMarginLeft, fSubAxisY,
     253                         width() - m_iMarginRight, fSubAxisY);
     254    }
     255
     256    /* draw X subaxes: */
     257    int iXSubAxisCount = 5;
     258    for (int i = 0; i < iXSubAxisCount; ++i)
     259    {
     260        float fSubAxisX = m_iMarginLeft + (i + 1) * iChartWidth / (float) (iXSubAxisCount + 1);
     261        painter.drawLine(fSubAxisX, m_iMarginTop, fSubAxisX, height() - m_iMarginBottom);
     262    }
     263
     264    QFontMetrics fontMetrics(painter.font());
     265    int iFontHeight = fontMetrics.height();
     266
     267    /* Draw XAxis tick labels: */
     268    painter.setPen(mainAxisColor);
     269    drawXAxisLabels(painter, iXSubAxisCount);
     270
     271    /* Draw a half-transparent rectangle over the whole widget to indicate the it is disabled: */
     272    if (!isEnabled())
     273    {
     274        painter.setPen(Qt::NoPen);
     275        painter.setBrush(QColor(60, 60, 60, 50));
     276        painter.drawRect(QRect(0, 0, width(), height()));
     277        return;
     278    }
     279
     280    if (!m_pSubMetric || iMaximumQueueSize <= 1)
     281        return;
     282
     283    ULONG iMaximum = m_pSubMetric->maximum();
     284    if (iMaximum == 0)
     285        return;
     286    /* Draw the data lines: */
     287    float fBarWidth = iChartWidth / (float) (iMaximumQueueSize - 1);
     288    float fH = iChartHeight / (float)iMaximum;
     289    for (int k = 0; k < DATA_SERIES_SIZE; ++k)
     290    {
     291        if (m_fUseGradientLineColor)
     292        {
     293            QLinearGradient gradient(0, 0, 0, iChartHeight);
     294            gradient.setColorAt(0, Qt::black);
     295            gradient.setColorAt(1, m_dataSeriesColor[k]);
     296            painter.setPen(QPen(gradient, 2.5));
     297        }
     298
     299        const QQueue<ULONG> *data = m_pSubMetric->data(k);
     300        if (!m_fUseGradientLineColor)
     301            painter.setPen(QPen(m_dataSeriesColor[k], 2.5));
     302        for (int i = 0; i < data->size() - 1; ++i)
     303        {
     304            int j = i + 1;
     305            float fHeight = fH * data->at(i);
     306            float fX = (width() - m_iMarginRight) - ((data->size() -i - 1) * fBarWidth);
     307            float fHeight2 = fH * data->at(j);
     308            float fX2 = (width() - m_iMarginRight) - ((data->size() -j - 1) * fBarWidth);
     309            QLineF bar(fX, height() - (fHeight + m_iMarginBottom), fX2, height() - (fHeight2 + m_iMarginBottom));
     310            painter.drawLine(bar);
     311        }
     312    }
     313
     314    /* Draw YAxis tick labels: */
     315    painter.setPen(mainAxisColor);
     316    for (int i = 0; i < iYSubAxisCount + 2; ++i)
     317    {
     318        int iTextY = 0.5 * iFontHeight + m_iMarginTop + i * iChartHeight / (float) (iYSubAxisCount + 1);
     319        QString strValue;
     320        ULONG iValue = (iYSubAxisCount + 1 - i) * (iMaximum / (float) (iYSubAxisCount + 1));
     321        if (m_pSubMetric->unit().compare("%", Qt::CaseInsensitive) == 0)
     322            strValue = QString::number(iValue);
     323        else if (m_pSubMetric->unit().compare("kb", Qt::CaseInsensitive) == 0)
     324            strValue = uiCommon().formatSize(_1K * (quint64)iValue, iDecimalCount);
     325        else if (m_pSubMetric->unit().compare("b", Qt::CaseInsensitive) == 0 ||
     326                 m_pSubMetric->unit().compare("b/s", Qt::CaseInsensitive) == 0)
     327            strValue = uiCommon().formatSize(iValue, iDecimalCount);
     328        painter.drawText(width() - 0.9 * m_iMarginRight, iTextY, strValue);
     329    }
     330
     331    if (m_fDrawPieChart)
     332        drawPieCharts(painter, iMaximum);
     333}
     334
     335void UIChart::drawXAxisLabels(QPainter &painter, int iXSubAxisCount)
     336{
     337    QFontMetrics fontMetrics(painter.font());
     338    int iFontHeight = fontMetrics.height();
     339    int iChartWidth = width() - (m_iMarginLeft + m_iMarginRight);
     340    int iTotalSeconds = iPeriod * iMaximumQueueSize;
     341    for (int i = 0; i < iXSubAxisCount + 2; ++i)
     342    {
     343        int iTextX = m_iMarginLeft + i * iChartWidth / (float) (iXSubAxisCount + 1);
     344        QString strCurentSec = QString::number(iTotalSeconds - i * iTotalSeconds / (float)(iXSubAxisCount + 1));
     345        int iTextWidth = fontMetrics.width(strCurentSec);
     346        if (i == 0)
     347        {
     348            strCurentSec += " " + m_strXAxisLabel;
     349            painter.drawText(iTextX, height() - m_iMarginBottom + iFontHeight, strCurentSec);
     350        }
     351        else
     352            painter.drawText(iTextX - 0.5 * iTextWidth, height() - m_iMarginBottom + iFontHeight, strCurentSec);
     353    }
     354}
     355
     356void UIChart::drawPieCharts(QPainter &painter, ULONG iMaximum)
     357{
     358    for (int i = 0; i < DATA_SERIES_SIZE; ++i)
     359    {
     360        /* Draw the pie chart for the 0th data series only: */
     361        const QQueue<ULONG> *data = m_pSubMetric->data(i);
     362        if (!data || data->isEmpty())
     363            continue;
     364
     365        /* Draw a whole non-filled circle: */
     366        painter.setPen(QPen(Qt::gray, 1));
     367        painter.drawArc(m_pieChartRect[i], 0, 3600 * 16);
     368
     369        QPointF center(m_pieChartRect[i].center());
     370        QPainterPath fillPath;
     371        fillPath.moveTo(center);
     372        fillPath.arcTo(m_pieChartRect[i], 90/*startAngle*/,
     373                       -1 * 360 /*sweepLength*/);
     374
     375        /* First draw a white filled circle and that the arc for data: */
     376        painter.setPen(Qt::NoPen);
     377        painter.setBrush(QColor(255, 255, 255, 175));
     378        painter.drawPath(fillPath);
     379
     380        /* Prepare the gradient for the pie chart: */
     381        QConicalGradient pieGradient;
     382        pieGradient.setCenter(m_pieChartRect[i].center());
     383        pieGradient.setAngle(90);
     384        pieGradient.setColorAt(0, Qt::black);
     385        pieGradient.setColorAt(1, m_dataSeriesColor[i]);
     386
     387        QPainterPath dataPath;
     388        dataPath.moveTo(center);
     389        float fAngle = 360.f * data->back() / (float)iMaximum;
     390        dataPath.arcTo(m_pieChartRect[i], 90/*startAngle*/,
     391                       -1 * fAngle /*sweepLength*/);
     392        painter.setBrush(pieGradient);
     393        painter.drawPath(dataPath);
     394
     395    }
     396}
     397
     398/*********************************************************************************************************************************
     399*   UISubMetric implementation.                                                                                     *
     400*********************************************************************************************************************************/
     401
     402UISubMetric::UISubMetric(const QString &strName, const QString &strUnit, int iMaximumQueueSize)
     403    : m_strName(strName)
     404    , m_strUnit(strUnit)
     405    , m_iMaximum(0)
     406    , m_iMaximumQueueSize(iMaximumQueueSize)
     407    , m_fRequiresGuestAdditions(false)
     408{
     409}
     410
     411UISubMetric::UISubMetric()
     412    : m_iMaximumQueueSize(0)
     413{
     414}
     415
     416const QString &UISubMetric::name() const
     417{
     418    return m_strName;
     419}
     420
     421void UISubMetric::setMaximum(ULONG iMaximum)
     422{
     423    m_iMaximum = iMaximum;
     424}
     425
     426ULONG UISubMetric::maximum() const
     427{
     428    return m_iMaximum;
     429}
     430
     431void UISubMetric::setUnit(QString strUnit)
     432{
     433    m_strUnit = strUnit;
     434
     435}
     436const QString &UISubMetric::unit() const
     437{
     438    return m_strUnit;
     439}
     440
     441void UISubMetric::addData(int iDataSeriesIndex, ULONG fData)
     442{
     443    if (iDataSeriesIndex >= DATA_SERIES_SIZE)
     444        return;
     445    m_data[iDataSeriesIndex].enqueue(fData);
     446    if (m_data[iDataSeriesIndex].size() > iMaximumQueueSize)
     447        m_data[iDataSeriesIndex].dequeue();
     448}
     449
     450const QQueue<ULONG> *UISubMetric::data(int iDataSeriesIndex) const
     451{
     452    if (iDataSeriesIndex >= DATA_SERIES_SIZE)
     453        return 0;
     454    return &m_data[iDataSeriesIndex];
     455}
     456
     457bool UISubMetric::requiresGuestAdditions() const
     458{
     459    return m_fRequiresGuestAdditions;
     460}
     461
     462void UISubMetric::setRequiresGuestAdditions(bool fRequiresGAs)
     463{
     464    m_fRequiresGuestAdditions = fRequiresGAs;
     465}
     466
     467/*********************************************************************************************************************************
     468*   UIInformationRuntime implementation.                                                                                     *
     469*********************************************************************************************************************************/
     470
     471UIInformationRuntime::UIInformationRuntime(QWidget *pParent, const CMachine &machine, const CConsole &console, const UISession *pSession)
    42472    : QIWithRetranslateUI<QWidget>(pParent)
     473    , m_fGuestAdditionsAvailable(false)
    43474    , m_machine(machine)
    44475    , m_console(console)
    45 {
     476    , m_pMainLayout(0)
     477    , m_pTimer(0)
     478    , m_strCPUMetricName("CPU Load")
     479    , m_strRAMMetricName("RAM Usage")
     480    , m_strDiskMetricName("Disk Usage")
     481    , m_strNetMetricName("Net")
     482{
     483    if (!m_console.isNull())
     484        m_comGuest = m_console.GetGuest();
     485    m_fGuestAdditionsAvailable = guestAdditionsAvailable(6 /* minimum major version */);
     486
     487    connect(pSession, &UISession::sigAdditionsStateChange, this, &UIInformationRuntime::sltGuestAdditionsStateChange);
     488    preparePerformaceCollector();
     489    prepareObjects();
     490    enableDisableGuestAdditionDependedWidgets(m_fGuestAdditionsAvailable);
    46491    retranslateUi();
    47     createTableItems();
     492}
     493
     494UIInformationRuntime::~UIInformationRuntime()
     495{
    48496}
    49497
    50498void UIInformationRuntime::retranslateUi()
    51499{
    52     m_strRuntimeTitle = QApplication::translate("UIVMInformationDialog", "Runtime Attributes");
    53 }
    54 
    55 void UIInformationRuntime::createTableItems()
    56 {
    57     // if (!m_pTableWidget)
    58     //     return;
    59     // QFontMetrics fontMetrics(m_pTableWidget->font());
    60     // QTextDocument textDocument;
    61     // int iMaxColumn1Length = 0;
    62 
    63     // insertTitleRow(m_strRuntimeTitle, UIIconPool::iconSet(":/state_running_16px.png"), fontMetrics);
    64 
    65 
    66     // insertInfoRows(runTimeAttributes(),
    67     //                fontMetrics, textDocument, iMaxColumn1Length);
    68 
    69 
    70 
    71     // m_pTableWidget->resizeColumnToContents(0);
    72     // /* Resize the column 1 a bit larger than the max string if contains: */
    73     // m_pTableWidget->setColumnWidth(1, 1.5 * iMaxColumn1Length);
    74     // m_pTableWidget->resizeColumnToContents(2);
     500    foreach (UIChart *pChart, m_charts)
     501        pChart->setXAxisLabel(QApplication::translate("UIVMInformationDialog", "Seconds"));
     502    int iMaximum = 0;
     503    m_strCPUInfoLabelTitle = QApplication::translate("UIVMInformationDialog", "CPU Load");
     504    iMaximum = qMax(iMaximum, m_strCPUInfoLabelTitle.length());
     505
     506    m_strCPUInfoLabelGuest = QApplication::translate("UIVMInformationDialog", "Guest Load");
     507    iMaximum = qMax(iMaximum, m_strCPUInfoLabelGuest.length());
     508    m_strCPUInfoLabelVMM = QApplication::translate("UIVMInformationDialog", "VMM Load");
     509    iMaximum = qMax(iMaximum, m_strCPUInfoLabelVMM.length());
     510
     511    m_strRAMInfoLabelTitle = QApplication::translate("UIVMInformationDialog", "RAM Usage");
     512    iMaximum = qMax(iMaximum, m_strRAMInfoLabelTitle.length());
     513    m_strRAMInfoLabelTotal = QApplication::translate("UIVMInformationDialog", "Total");
     514    iMaximum = qMax(iMaximum, m_strRAMInfoLabelTotal.length());
     515    m_strRAMInfoLabelFree = QApplication::translate("UIVMInformationDialog", "Free");
     516    iMaximum = qMax(iMaximum, m_strRAMInfoLabelFree.length());
     517    m_strRAMInfoLabelUsed = QApplication::translate("UIVMInformationDialog", "Used");
     518    iMaximum = qMax(iMaximum, m_strRAMInfoLabelUsed.length());
     519    m_strNetInfoLabelTitle = QApplication::translate("UIVMInformationDialog", "Network");
     520    iMaximum = qMax(iMaximum, m_strNetInfoLabelTitle.length());
     521    m_strNetInfoLabelReceived = QApplication::translate("UIVMInformationDialog", "Received");
     522    iMaximum = qMax(iMaximum, m_strNetInfoLabelReceived.length());
     523    m_strNetInfoLabelTransmitted = QApplication::translate("UIVMInformationDialog", "Transmitted");
     524    iMaximum = qMax(iMaximum, m_strNetInfoLabelTransmitted.length());
     525    m_strNetInfoLabelMaximum = QApplication::translate("UIVMInformationDialog", "Maximum");
     526    iMaximum = qMax(iMaximum, m_strNetInfoLabelMaximum.length());
     527
     528    /* Compute the maximum label string length and set it as a fixed width to labels to prevent always changing widths: */
     529    /* Add m_iDecimalCount plus 3 characters for the number and 2 for unit string: */
     530    iMaximum += (iDecimalCount + 5);
     531    if (!m_infoLabels.isEmpty())
     532    {
     533        QLabel *pLabel = m_infoLabels.begin().value();
     534        if (pLabel)
     535        {
     536            QFontMetrics labelFontMetric(pLabel->font());
     537            int iWidth = iMaximum * labelFontMetric.width('x');
     538            foreach (QLabel *pInfoLabel, m_infoLabels)
     539                pInfoLabel->setFixedWidth(iWidth);
     540        }
     541    }
     542
     543}
     544
     545void UIInformationRuntime::prepareObjects()
     546{
     547    m_pMainLayout = new QGridLayout(this);
     548    if (m_pMainLayout)
     549    {
     550        m_pMainLayout->setSpacing(10);
     551    }
     552
     553    m_pTimer = new QTimer(this);
     554    if (m_pTimer)
     555    {
     556        connect(m_pTimer, &QTimer::timeout, this, &UIInformationRuntime::sltTimeout);
     557        m_pTimer->start(1000 * iPeriod);
     558    }
     559
     560    QStringList chartOder;
     561    chartOder << m_strCPUMetricName << m_strRAMMetricName << m_strDiskMetricName << m_strNetMetricName;
     562    int iRow = 0;
     563    foreach (const QString &strMetricName, chartOder)
     564    {
     565        if (!m_subMetrics.contains(strMetricName))
     566            continue;
     567        QLabel *pLabel = new QLabel;
     568        pLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
     569        m_pMainLayout->addWidget(pLabel, iRow, 0);
     570        m_infoLabels.insert(strMetricName, pLabel);
     571
     572        UIChart *pChart = new UIChart(this, &(m_subMetrics[strMetricName]));
     573        m_charts.insert(strMetricName, pChart);
     574        pChart->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
     575        m_pMainLayout->addWidget(pChart, iRow, 1);
     576        ++iRow;
     577    }
     578
     579    /* Configure charts: */
     580    if (m_charts.contains(m_strNetMetricName) && m_charts[m_strNetMetricName])
     581    {
     582        m_charts[m_strNetMetricName]->setDrawPieChart(false);
     583        m_charts[m_strNetMetricName]->setUseGradientLineColor(false);
     584    }
     585    if (m_charts.contains(m_strCPUMetricName) && m_charts[m_strCPUMetricName])
     586        m_charts[m_strCPUMetricName]->setUseGradientLineColor(false);
     587    if (m_charts.contains(m_strRAMMetricName) && m_charts[m_strRAMMetricName])
     588        m_charts[m_strRAMMetricName]->setUseGradientLineColor(false);
     589
     590    QWidget *bottomSpacerWidget = new QWidget(this);
     591    bottomSpacerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
     592    bottomSpacerWidget->setVisible(true);
     593    // QPalette pal = bottomSpacerWidget->palette();
     594    // pal.setColor(QPalette::Background, Qt::green);
     595    // bottomSpacerWidget->setAutoFillBackground(true);
     596    // bottomSpacerWidget->setPalette(pal);
     597
     598    m_pMainLayout->addWidget(bottomSpacerWidget, iRow, 0, 1, 2);
     599}
     600
     601void UIInformationRuntime::sltTimeout()
     602{
     603
     604    if (m_performanceMonitor.isNull())
     605        return;
     606    QVector<QString> allNames;// = new ArrayList<IUnknown>();
     607    QVector<CUnknown> allObjects;// = new ArrayList<IUnknown>();
     608
     609    QVector<QString>  aReturnNames;
     610    QVector<CUnknown>  aReturnObjects;
     611    QVector<QString>  aReturnUnits;
     612    QVector<ULONG>  aReturnScales;
     613    QVector<ULONG>  aReturnSequenceNumbers;
     614    QVector<ULONG>  aReturnDataIndices;
     615    QVector<ULONG>  aReturnDataLengths;
     616
     617    QVector<LONG> returnData = m_performanceMonitor.QueryMetricsData(m_nameList,
     618                                                                     m_objectList,
     619                                                                     aReturnNames,
     620                                                                     aReturnObjects,
     621                                                                     aReturnUnits,
     622                                                                     aReturnScales,
     623                                                                     aReturnSequenceNumbers,
     624                                                                     aReturnDataIndices,
     625                                                                     aReturnDataLengths);
     626    quint64 iTotalRAM = 0;
     627    quint64 iFreeRAM = 0;
     628    ULONG iReceiveRate = 0;
     629    ULONG  iTransmitRate = 0;
     630
     631    for (int i = 0; i < aReturnNames.size(); ++i)
     632    {
     633        if (aReturnDataLengths[i] == 0)
     634            continue;
     635        /* Read the last of the return data disregarding the rest since we are caching the data in GUI side: */
     636        float fData = returnData[aReturnDataIndices[i] + aReturnDataLengths[i] - 1] / (float)aReturnScales[i];
     637        if (aReturnNames[i].contains("RAM", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
     638        {
     639            if (aReturnNames[i].contains("Total", Qt::CaseInsensitive))
     640                iTotalRAM = (quint64)fData;
     641            if (aReturnNames[i].contains("Free", Qt::CaseInsensitive))
     642                iFreeRAM = (quint64)fData;
     643        }
     644        else if (aReturnNames[i].contains("Net/Rate", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
     645        {
     646            if (aReturnNames[i].contains("Rx", Qt::CaseInsensitive))
     647                iReceiveRate = fData;
     648            if (aReturnNames[i].contains("Tx", Qt::CaseInsensitive))
     649                iTransmitRate = fData;
     650        }
     651    }
     652
     653    (void)iReceiveRate;
     654    (void)iTransmitRate;
     655    /* Update the CPU load chart with values we get from IMachineDebugger::getCPULoad(..): */
     656    if (m_subMetrics.contains(m_strCPUMetricName))
     657    {
     658        ULONG aPctExecuting;
     659        ULONG aPctHalted;
     660        ULONG aPctOther;
     661        m_machineDebugger.GetCPULoad(0x7fffffff, aPctExecuting, aPctHalted, aPctOther);
     662        updateCPUGraphsAndMetric(aPctExecuting, aPctOther);
     663    }
     664
     665    if (m_subMetrics.contains(m_strRAMMetricName))
     666        updateRAMGraphsAndMetric(iTotalRAM, iFreeRAM);
     667    if (m_subMetrics.contains(m_strNetMetricName))
     668        updateNewGraphsAndMetric(iReceiveRate, iTransmitRate);
     669
     670}
     671
     672void UIInformationRuntime::sltGuestAdditionsStateChange()
     673{
     674    bool fGuestAdditionsAvailable = guestAdditionsAvailable(6 /* minimum major version */);
     675    if (m_fGuestAdditionsAvailable == fGuestAdditionsAvailable)
     676        return;
     677    m_fGuestAdditionsAvailable = fGuestAdditionsAvailable;
     678    enableDisableGuestAdditionDependedWidgets(m_fGuestAdditionsAvailable);
     679}
     680
     681void UIInformationRuntime::preparePerformaceCollector()
     682{
     683    m_performanceMonitor = uiCommon().virtualBox().GetPerformanceCollector();
     684    m_machineDebugger = m_console.GetDebugger();
     685
     686    if (m_performanceMonitor.isNull())
     687        return;
     688
     689    // m_nameList << "Guest/RAM/Usage*";
     690    m_nameList << "Guest/RAM/Usage*";
     691    m_nameList << "Net/Rate*";
     692
     693
     694    m_objectList = QVector<CUnknown>(m_nameList.size(), CUnknown());
     695    m_performanceMonitor.SetupMetrics(m_nameList, m_objectList, iPeriod, iMetricSetupCount);
     696    {
     697        QVector<CPerformanceMetric> metrics = m_performanceMonitor.GetMetrics(m_nameList, m_objectList);
     698        for (int i = 0; i < metrics.size(); ++i)
     699        {
     700            QString strName(metrics[i].GetMetricName());
     701            if (!strName.contains(':'))
     702            {
     703                if (strName.contains("RAM", Qt::CaseInsensitive) && strName.contains("Free", Qt::CaseInsensitive))
     704                {
     705                    UISubMetric newMetric(m_strRAMMetricName, metrics[i].GetUnit(), iMaximumQueueSize);
     706                    newMetric.setRequiresGuestAdditions(true);
     707                    m_subMetrics.insert(m_strRAMMetricName, newMetric);
     708                }
     709                else if (strName.contains("Net", Qt::CaseInsensitive))
     710                {
     711                    UISubMetric newMetric(m_strNetMetricName, metrics[i].GetUnit(), iMaximumQueueSize);
     712                    newMetric.setRequiresGuestAdditions(true);
     713                    m_subMetrics.insert(m_strNetMetricName, newMetric);
     714                }
     715            }
     716        }
     717    }
     718    m_subMetrics.insert(m_strCPUMetricName, UISubMetric(m_strCPUMetricName, "%", iMaximumQueueSize));
     719}
     720
     721bool UIInformationRuntime::guestAdditionsAvailable(int iMinimumMajorVersion)
     722{
     723    if (m_comGuest.isNull())
     724        return false;
     725    bool fGuestAdditionsStatus = m_comGuest.GetAdditionsStatus(m_comGuest.GetAdditionsRunLevel());
     726    if (fGuestAdditionsStatus)
     727    {
     728        QStringList versionStrings = m_comGuest.GetAdditionsVersion().split('.', QString::SkipEmptyParts);
     729        if (!versionStrings.isEmpty())
     730        {
     731            bool fConvert = false;
     732            int iMajorVersion = versionStrings[0].toInt(&fConvert);
     733            if (fConvert && iMajorVersion >= iMinimumMajorVersion)
     734                return true;
     735        }
     736    }
     737    return false;
     738}
     739
     740void UIInformationRuntime::enableDisableGuestAdditionDependedWidgets(bool fEnable)
     741{
     742    for (QMap<QString, UISubMetric>::const_iterator iterator =  m_subMetrics.begin();
     743         iterator != m_subMetrics.end(); ++iterator)
     744    {
     745        if (!iterator.value().requiresGuestAdditions())
     746            continue;
     747        if (m_charts.contains(iterator.key()) && m_charts[iterator.key()])
     748        {
     749            m_charts[iterator.key()]->setEnabled(fEnable);
     750            m_charts[iterator.key()]->update();
     751        }
     752        if (m_infoLabels.contains(iterator.key()) && m_infoLabels[iterator.key()])
     753        {
     754            m_infoLabels[iterator.key()]->setEnabled(fEnable);
     755            m_infoLabels[iterator.key()]->update();
     756        }
     757    }
     758}
     759
     760void UIInformationRuntime::updateCPUGraphsAndMetric(ULONG iExecutingPercentage, ULONG iOtherPercentage)
     761{
     762    UISubMetric &CPUMetric = m_subMetrics[m_strCPUMetricName];
     763    CPUMetric.addData(0, iExecutingPercentage);
     764    CPUMetric.addData(1, iOtherPercentage);
     765    CPUMetric.setMaximum(100);
     766    if (m_infoLabels.contains(m_strCPUMetricName)  && m_infoLabels[m_strCPUMetricName])
     767    {
     768        QString strInfo;
     769        QString strReceiveColor;
     770        if (m_infoLabels[m_strCPUMetricName]->isEnabled())
     771            strInfo = QString("<b>%1</b></b><br/><font color=\"%2\">%3: %4%5</font><br/><font color=\"%6\">%7: %8%9</font>")
     772                .arg(m_strCPUInfoLabelTitle)
     773                .arg(dataColorString(m_strCPUMetricName, 0))
     774                .arg(m_strCPUInfoLabelGuest).arg(QString::number(iExecutingPercentage)).arg(CPUMetric.unit())
     775                .arg(dataColorString(m_strCPUMetricName, 1))
     776                .arg(m_strCPUInfoLabelVMM).arg(QString::number(iOtherPercentage)).arg(CPUMetric.unit());
     777        else
     778            strInfo = QString("<b>%1</b><br/>%2%3").arg(m_strCPUInfoLabelTitle).arg("--").arg("%");
     779        m_infoLabels[m_strCPUMetricName]->setText(strInfo);
     780    }
     781
     782    if (m_charts.contains(m_strCPUMetricName))
     783        m_charts[m_strCPUMetricName]->update();
     784}
     785
     786void UIInformationRuntime::updateRAMGraphsAndMetric(quint64 iTotalRAM, quint64 iFreeRAM)
     787{
     788    UISubMetric &RAMMetric = m_subMetrics[m_strRAMMetricName];
     789    RAMMetric.setMaximum(iTotalRAM);
     790    RAMMetric.addData(0, iTotalRAM - iFreeRAM);
     791    if (m_infoLabels.contains(m_strRAMMetricName)  && m_infoLabels[m_strRAMMetricName])
     792    {
     793        QString strInfo;
     794        if (m_infoLabels[m_strRAMMetricName]->isEnabled())
     795            strInfo = QString("<b>%1</b><br/>%2: %3<br/>%4: %5<br/>%6: %7").arg(m_strRAMInfoLabelTitle).arg(m_strRAMInfoLabelTotal).arg(uiCommon().formatSize(_1K * iTotalRAM, iDecimalCount))
     796                .arg(m_strRAMInfoLabelFree).arg(uiCommon().formatSize(_1K * (iFreeRAM), iDecimalCount))
     797                .arg(m_strRAMInfoLabelUsed).arg(uiCommon().formatSize(_1K * (iTotalRAM - iFreeRAM), iDecimalCount));
     798        else
     799            strInfo = QString("<b>%1</b><br/>%2: %3<br/>%4: %5<br/>%6: %7").arg(m_strRAMInfoLabelTitle).arg(m_strRAMInfoLabelTotal).arg("---").arg(m_strRAMInfoLabelFree).arg("---").arg(m_strRAMInfoLabelUsed).arg("---");
     800        m_infoLabels[m_strRAMMetricName]->setText(strInfo);
     801    }
     802    if (m_charts.contains(m_strRAMMetricName))
     803        m_charts[m_strRAMMetricName]->update();
     804}
     805
     806void UIInformationRuntime::updateNewGraphsAndMetric(ULONG iReceiveRate, ULONG iTransmitRate)
     807{
     808   UISubMetric &NetMetric = m_subMetrics[m_strNetMetricName];
     809
     810   NetMetric.addData(0, iReceiveRate);
     811   NetMetric.addData(1, iTransmitRate);
     812
     813   ULONG iMaximum = qMax(NetMetric.maximum(), (ULONG)qMax(iReceiveRate, iTransmitRate));
     814   NetMetric.setMaximum(iMaximum);
     815
     816    if (m_infoLabels.contains(m_strNetMetricName)  && m_infoLabels[m_strNetMetricName])
     817    {
     818        QString strInfo;
     819        QString strReceiveColor;
     820        if (m_infoLabels[m_strNetMetricName]->isEnabled())
     821            strInfo = QString("<b>%1</b></b><br/><font color=\"%2\">%3: %4</font><br/><font color=\"%5\">%6: %7</font><br/>%8: %9")
     822                .arg(m_strNetInfoLabelTitle)
     823                .arg(dataColorString(m_strNetMetricName, 0))
     824                .arg(m_strNetInfoLabelReceived).arg(uiCommon().formatSize((quint64)iReceiveRate, iDecimalCount))
     825                .arg(dataColorString(m_strNetMetricName, 1))
     826                .arg(m_strNetInfoLabelTransmitted).arg(uiCommon().formatSize((quint64)iTransmitRate, iDecimalCount))
     827                .arg(m_strNetInfoLabelMaximum).arg(uiCommon().formatSize((quint64)iMaximum, iDecimalCount));
     828        else
     829            strInfo = QString("<b>%1</b><br/>%2: %3<br/>%4: %5<br/>%6: %7").arg(m_strNetInfoLabelTitle).arg(m_strNetInfoLabelReceived).arg("---").arg(m_strNetInfoLabelTransmitted).arg("---");
     830        m_infoLabels[m_strNetMetricName]->setText(strInfo);
     831    }
     832   if (m_charts.contains(m_strNetMetricName))
     833       m_charts[m_strNetMetricName]->update();
     834
     835}
     836
     837QString UIInformationRuntime::dataColorString(const QString &strChartName, int iDataIndex)
     838{
     839    if (!m_charts.contains(strChartName))
     840        return QColor(Qt::red).name(QColor::HexRgb);
     841    UIChart *pChart = m_charts[strChartName];
     842    if (!pChart)
     843        return QColor(Qt::red).name(QColor::HexRgb);
     844    return pChart->dataSeriesColor(iDataIndex).name(QColor::HexRgb);
    75845}
    76846
     
    214984    return textTable;
    215985}
     986
     987#include "UIInformationRuntime.moc"
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIInformationRuntime.h

    r80379 r80381  
    2424/* Qt includes: */
    2525#include <QWidget>
     26#include <QMap>
     27#include <QQueue>
     28
    2629
    2730/* COM includes: */
    2831#include "COMEnums.h"
     32#include "CConsole.h"
     33#include "CGuest.h"
    2934#include "CMachine.h"
    30 #include "CConsole.h"
     35#include "CMachineDebugger.h"
     36#include "CPerformanceCollector.h"
    3137
    3238/* GUI includes: */
     
    3541
    3642/* Forward declarations: */
    37 class QVBoxLayout;
    38 class UIInformationView;
    39 class UIInformationModel;
    40 class UIVMItem;
     43class QTimer;
     44class QGridLayout;
     45class QLabel;
     46class UIChart;
     47class UISession;
    4148
     49class UISubMetric
     50{
     51public:
    4252
     53    UISubMetric(const QString &strName, const QString &strUnit, int iMaximumQueueSize);
     54    UISubMetric();
     55    const QString &name() const;
     56
     57    void setMaximum(ULONG iMaximum);
     58    ULONG maximum() const;
     59
     60    void setUnit(QString strUnit);
     61    const QString &unit() const;
     62
     63    void addData(int iDataSeriesIndex, ULONG fData);
     64    const QQueue<ULONG> *data(int iDataSeriesIndex) const;
     65
     66    bool requiresGuestAdditions() const;
     67    void setRequiresGuestAdditions(bool fRequiresGAs);
     68
     69private:
     70
     71    QString m_strName;
     72    QString m_strUnit;
     73    ULONG m_iMaximum;
     74    QQueue<ULONG> m_data[2];
     75    int m_iMaximumQueueSize;
     76    bool m_fRequiresGuestAdditions;
     77};
     78
     79/** UIInformationRuntime class displays some high level performance metric of the guest system.
     80  * The values are read in certain periods and cached in the GUI side. Currently we draw some line charts
     81  * and pie charts (where applicable) alongside with some text. */
    4382class UIInformationRuntime : public QIWithRetranslateUI<QWidget>
    4483{
     
    4786public:
    4887
    49     UIInformationRuntime(QWidget *pParent, const CMachine &machine, const CConsole &console);
     88    /** Constructs information-tab passing @a pParent to the QWidget base-class constructor.
     89      * @param machine is machine reference.
     90      * @param console is machine console reference. */
     91    UIInformationRuntime(QWidget *pParent, const CMachine &machine, const CConsole &console, const UISession *pSession);
     92    ~UIInformationRuntime();
    5093
    5194protected:
     95    void retranslateUi();
    5296
    53     void retranslateUi() /* override */;
    54     void createTableItems() /* override */;
     97private slots:
     98
     99    void sltTimeout();
     100    void sltGuestAdditionsStateChange();
    55101
    56102private:
     103
     104    /** Prepares layout. */
     105    void prepareObjects();
     106    void preparePerformaceCollector();
     107    bool guestAdditionsAvailable(int iMinimumMajorVersion);
     108    void enableDisableGuestAdditionDependedWidgets(bool fEnable);
     109    void updateCPUGraphsAndMetric(ULONG iLoadPercentage, ULONG iOtherPercentage);
     110    void updateRAMGraphsAndMetric(quint64 iTotalRAM, quint64 iFreeRAM);
     111    void updateNewGraphsAndMetric(ULONG iReceiveRate, ULONG iTransmitRate);
     112    QString dataColorString(const QString &strChartName, int iDataIndex);
    57113    UITextTable runTimeAttributes();
    58114
     115    bool m_fGuestAdditionsAvailable;
     116    /** Holds the machine instance. */
    59117    CMachine m_machine;
     118    /** Holds the console instance. */
    60119    CConsole m_console;
     120    CGuest m_comGuest;
     121
     122    CPerformanceCollector m_performanceMonitor;
     123    CMachineDebugger      m_machineDebugger;
     124    /** Holds the instance of layout we create. */
     125    QGridLayout *m_pMainLayout;
     126    QTimer *m_pTimer;
     127
     128    QVector<QString> m_nameList;
     129    QVector<CUnknown> m_objectList;
     130
     131    QMap<QString, UISubMetric> m_subMetrics;
     132    QMap<QString,UIChart*>  m_charts;
     133    QMap<QString,QLabel*>  m_infoLabels;
     134
     135    /** @name These metric names are used for map keys to identify metrics.
     136      * @{ */
     137        QString m_strCPUMetricName;
     138        QString m_strRAMMetricName;
     139        QString m_strDiskMetricName;
     140        QString m_strNetMetricName;
     141    /** @} */
    61142
    62143    /** @name Cached translated string.
    63      * @{ */
    64        QString m_strRuntimeTitle;
     144      * @{ */
     145        /** CPU info label strings. */
     146        QString m_strCPUInfoLabelTitle;
     147        QString m_strCPUInfoLabelGuest;
     148        QString  m_strCPUInfoLabelVMM;
     149        /** RAM usage info label strings. */
     150        QString m_strRAMInfoLabelTitle;
     151        QString m_strRAMInfoLabelTotal;
     152        QString m_strRAMInfoLabelFree;
     153        QString m_strRAMInfoLabelUsed;
     154        /** Net traffic info label strings. */
     155        QString m_strNetInfoLabelTitle;
     156        QString m_strNetInfoLabelReceived;
     157        QString m_strNetInfoLabelTransmitted;
     158        QString m_strNetInfoLabelMaximum;
    65159    /** @} */
     160
    66161
    67162};
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIVMInformationDialog.cpp

    r80369 r80381  
    3636#include "UIInformationConfiguration.h"
    3737#include "UIInformationRuntime.h"
    38 #include "UIPerformanceMonitor.h"
    3938#include "UIGuestProcessControlWidget.h"
    4039#include "UIMachine.h"
     
    239238        /* Create Runtime Information tab: */
    240239        UIInformationRuntime *pInformationRuntimeWidget =
    241             new UIInformationRuntime(this, m_pMachineWindow->machine(), m_pMachineWindow->console());
     240            new UIInformationRuntime(this, m_pMachineWindow->machine(), m_pMachineWindow->console(), m_pMachineWindow->uisession());
    242241        if (pInformationRuntimeWidget)
    243242        {
     
    260259            m_tabs.insert(2, pGuestProcessControlWidget);
    261260            m_pTabWidget->addTab(m_tabs.value(2), QString());
    262         }
    263 
    264         UIPerformanceMonitor *pPerformanceMonitor =
    265             new UIPerformanceMonitor(this, m_pMachineWindow->machine(), m_pMachineWindow->console(), m_pMachineWindow->uisession());
    266         if (pPerformanceMonitor)
    267         {
    268             m_tabs.insert(3, pPerformanceMonitor);
    269             m_pTabWidget->addTab(m_tabs.value(3), QString());
    270261        }
    271262
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette