Changeset 103460 in vbox
- Timestamp:
- Feb 19, 2024 9:17:15 PM (11 months ago)
- Location:
- trunk/src/VBox/Debugger
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/VBoxDbgStatsQt.cpp
r103403 r103460 33 33 #include "VBoxDbgStatsQt.h" 34 34 35 #include <QLocale> 36 #include <QPushButton> 37 #include <QSpinBox> 38 #include <QLabel> 35 #include <QAction> 36 #include <QApplication> 39 37 #include <QCheckBox> 40 38 #include <QClipboard> 41 #include <QApplication> 39 #include <QContextMenuEvent> 40 #include <QDialog> 41 #include <QDialogButtonBox> 42 #include <QGroupBox> 43 #include <QGridLayout> 42 44 #include <QHBoxLayout> 45 #include <QHeaderView> 46 #include <QKeySequence> 47 #include <QLabel> 48 #include <QLineEdit> 49 #include <QLocale> 50 #include <QMessageBox> 51 #include <QPushButton> 52 #include <QSortFilterProxyModel> 53 #include <QSpinBox> 43 54 #include <QVBoxLayout> 44 #include <QKeySequence>45 #include <QAction>46 #include <QContextMenuEvent>47 #include <QHeaderView>48 #include <QSortFilterProxyModel>49 55 50 56 #include <iprt/errcore.h> … … 104 110 105 111 /** 112 * Filtering data. 113 */ 114 typedef struct VBoxGuiStatsFilterData 115 { 116 /** Number of instances. */ 117 static uint32_t volatile s_cInstances; 118 uint64_t uMinValue; 119 uint64_t uMaxValue; 120 QRegularExpression *pRegexName; 121 122 VBoxGuiStatsFilterData() 123 : uMinValue(0) 124 , uMaxValue(UINT64_MAX) 125 , pRegexName(NULL) 126 { 127 s_cInstances += 1; 128 } 129 130 ~VBoxGuiStatsFilterData() 131 { 132 if (pRegexName) 133 { 134 delete pRegexName; 135 pRegexName = NULL; 136 } 137 s_cInstances -= 1; 138 } 139 140 bool isAllDefaults(void) const 141 { 142 return (uMinValue == 0 || uMinValue == UINT64_MAX) 143 && (uMaxValue == 0 || uMaxValue == UINT64_MAX) 144 && pRegexName == NULL; 145 } 146 } VBoxGuiStatsFilterData; 147 148 149 /** 106 150 * A tree node representing a statistic sample. 107 151 * … … 121 165 /** Our index among the parent's children. */ 122 166 uint32_t iSelf; 167 /** Sub-tree filtering config (typically NULL). */ 168 VBoxGuiStatsFilterData *pFilter; 123 169 /** The unit string. (not allocated) */ 124 170 const char *pszUnit; 171 /** The delta. */ 172 int64_t i64Delta; 173 /** The name. */ 174 char *pszName; 175 /** The length of the name. */ 176 size_t cchName; 177 /** The description string. */ 178 QString *pDescStr; 179 /** The node state. */ 180 DBGGUISTATENODESTATE enmState; 125 181 /** The data type. 126 182 * For filler nodes not containing data, this will be set to STAMTYPE_INVALID. */ … … 150 206 QString *pStr; 151 207 } Data; 152 /** The delta. */153 int64_t i64Delta;154 /** The name. */155 char *pszName;156 /** The length of the name. */157 size_t cchName;158 /** The description string. */159 QString *pDescStr;160 /** The node state. */161 DBGGUISTATENODESTATE enmState;162 208 } DBGGUISTATSNODE; 163 209 … … 388 434 const char *pszUnit, STAMVISIBILITY enmVisibility, const char *pszDesc, void *pvUser); 389 435 436 public: 390 437 /** 391 438 * Calculates the full path of a node. … … 399 446 static ssize_t getNodePath(PCDBGGUISTATSNODE pNode, char *psz, ssize_t cch); 400 447 448 protected: 401 449 /** 402 450 * Calculates the full path of a node, returning the string pointer. … … 556 604 /** Gets the value/times. */ 557 605 static uint64_t getValueTimesAsUInt(PCDBGGUISTATSNODE pNode); 606 /** Gets the value/avg. */ 607 static uint64_t getValueOrAvgAsUInt(PCDBGGUISTATSNODE pNode); 558 608 /** Gets the minimum value. */ 559 609 static QString strMinValue(PCDBGGUISTATSNODE pNode); … … 584 634 static void destroyNode(PDBGGUISTATSNODE a_pNode); 585 635 636 public: 586 637 /** 587 638 * Converts an index to a node pointer. … … 657 708 }; 658 709 659 660 710 #ifdef VBOXDBG_WITH_SORTED_AND_FILTERED_STATS 711 661 712 /** 662 713 * Model using the VM / STAM interface as data source. … … 679 730 void setShowUnusedRows(bool a_fHide); 680 731 732 /** 733 * Notification that a filter has been added, removed or modified. 734 */ 735 void notifyFilterChanges(); 736 681 737 protected: 682 738 /** … … 701 757 bool m_fShowUnusedRows; 702 758 }; 759 760 761 /** 762 * Dialog for sub-tree filtering config. 763 */ 764 class VBoxDbgStatsFilterDialog : public QDialog 765 { 766 public: 767 /** 768 * Constructor. 769 * 770 * @param a_pNode The node to configure filtering for. 771 */ 772 VBoxDbgStatsFilterDialog(QWidget *a_pParent, PCDBGGUISTATSNODE a_pNode); 773 774 /** Destructor. */ 775 virtual ~VBoxDbgStatsFilterDialog(); 776 777 /** 778 * Returns a copy of the filter data or NULL if all defaults. 779 */ 780 VBoxGuiStatsFilterData *dupFilterData(void) const; 781 782 protected slots: 783 784 /** Validates and (maybe) accepts the dialog data. */ 785 void validateAndAccept(void); 786 787 protected: 788 /** 789 * Validates and converts the content of an uint64_t entry field.s 790 * 791 * @returns The converted value (or default) 792 * @param a_pField The entry field widget. 793 * @param a_uDefault The default return value. 794 * @param a_pszField The field name (for error messages). 795 * @param a_pLstErrors The error list to append validation errors to. 796 */ 797 static uint64_t validateUInt64Field(QLineEdit const *a_pField, uint64_t a_uDefault, 798 const char *a_pszField, QStringList *a_pLstErrors); 799 800 801 private: 802 /** The filter data. */ 803 VBoxGuiStatsFilterData m_Data; 804 805 /** The minium value/average entry field. */ 806 QLineEdit *m_pValueAvgMin; 807 /** The maxium value/average entry field. */ 808 QLineEdit *m_pValueAvgMax; 809 /** The name filtering regexp entry field. */ 810 QLineEdit *m_pNameRegExp; 811 812 /** Regular expression for validating the uint64_t entry fields. */ 813 static QRegularExpression const s_UInt64ValidatorRegExp; 814 815 /** 816 * Creates an entry field for a uint64_t value. 817 */ 818 static QLineEdit *createUInt64LineEdit(uint64_t uValue); 819 }; 820 703 821 #endif /* VBOXDBG_WITH_SORTED_AND_FILTERED_STATS */ 822 823 824 /********************************************************************************************************************************* 825 * Global Variables * 826 *********************************************************************************************************************************/ 827 /*static*/ uint32_t volatile VBoxGuiStatsFilterData::s_cInstances = 0; 704 828 705 829 … … 939 1063 } 940 1064 1065 VBoxGuiStatsFilterData const *pFilter = a_pNode->pFilter; 1066 if (!pFilter) 1067 { /* likely */ } 1068 else 1069 { 1070 delete pFilter; 1071 a_pNode->pFilter = NULL; 1072 } 1073 941 1074 #ifdef VBOX_STRICT 942 1075 /* poison it. */ … … 946 1079 a_pNode->papChildren++; 947 1080 a_pNode->cChildren = 8442; 1081 a_pNode->pFilter++; 948 1082 #endif 949 1083 … … 2486 2620 2487 2621 2622 /*static*/ uint64_t 2623 VBoxDbgStatsModel::getValueOrAvgAsUInt(PCDBGGUISTATSNODE pNode) 2624 { 2625 switch (pNode->enmType) 2626 { 2627 case STAMTYPE_COUNTER: 2628 return pNode->Data.Counter.c; 2629 2630 case STAMTYPE_PROFILE: 2631 case STAMTYPE_PROFILE_ADV: 2632 if (pNode->Data.Profile.cPeriods) 2633 return pNode->Data.Profile.cTicks / pNode->Data.Profile.cPeriods; 2634 return 0; 2635 2636 case STAMTYPE_RATIO_U32: 2637 case STAMTYPE_RATIO_U32_RESET: 2638 return RT_MAKE_U64(pNode->Data.RatioU32.u32A, pNode->Data.RatioU32.u32B); 2639 2640 case STAMTYPE_CALLBACK: 2641 return UINT64_MAX; 2642 2643 case STAMTYPE_U8: 2644 case STAMTYPE_U8_RESET: 2645 case STAMTYPE_X8: 2646 case STAMTYPE_X8_RESET: 2647 return pNode->Data.u8; 2648 2649 case STAMTYPE_U16: 2650 case STAMTYPE_U16_RESET: 2651 case STAMTYPE_X16: 2652 case STAMTYPE_X16_RESET: 2653 return pNode->Data.u16; 2654 2655 case STAMTYPE_U32: 2656 case STAMTYPE_U32_RESET: 2657 case STAMTYPE_X32: 2658 case STAMTYPE_X32_RESET: 2659 return pNode->Data.u32; 2660 2661 case STAMTYPE_U64: 2662 case STAMTYPE_U64_RESET: 2663 case STAMTYPE_X64: 2664 case STAMTYPE_X64_RESET: 2665 return pNode->Data.u64; 2666 2667 case STAMTYPE_BOOL: 2668 case STAMTYPE_BOOL_RESET: 2669 return pNode->Data.f; 2670 2671 default: 2672 AssertMsgFailed(("%d\n", pNode->enmType)); 2673 RT_FALL_THRU(); 2674 case STAMTYPE_INVALID: 2675 return UINT64_MAX; 2676 } 2677 } 2678 2679 2488 2680 /*static*/ QString 2489 2681 VBoxDbgStatsModel::strMinValue(PCDBGGUISTATSNODE pNode) … … 2676 2868 { 2677 2869 case 0: 2678 return QString(pNode->pszName); 2870 if (!pNode->pFilter) 2871 return QString(pNode->pszName); 2872 return QString(pNode->pszName) + " (*)"; 2679 2873 case 1: 2680 2874 return strUnit(pNode); … … 3055 3249 VBoxDbgStatsSortFileProxyModel::filterAcceptsRow(int a_iSrcRow, const QModelIndex &a_rSrcParent) const 3056 3250 { 3057 if (!m_fShowUnusedRows) 3058 { 3059 PDBGGUISTATSNODE const pParent = nodeFromIndex(a_rSrcParent); 3060 if (pParent) 3251 /* 3252 * Locate the node. 3253 */ 3254 PDBGGUISTATSNODE pParent = nodeFromIndex(a_rSrcParent); 3255 if (pParent) 3256 { 3257 if ((unsigned)a_iSrcRow < pParent->cChildren) 3061 3258 { 3062 if ((unsigned)a_iSrcRow < pParent->cChildren) 3259 PDBGGUISTATSNODE const pNode = pParent->papChildren[a_iSrcRow]; 3260 if (pNode) /* paranoia */ 3063 3261 { 3064 PDBGGUISTATSNODE const pNode = pParent->papChildren[a_iSrcRow]; 3065 if (pNode) /* paranoia */ 3262 /* 3263 * Apply the global unused-row filter. 3264 */ 3265 if (!m_fShowUnusedRows) 3066 3266 { 3067 3267 /* Only relevant for leaf nodes. */ … … 3144 3344 else 3145 3345 return false; 3346 } 3347 } 3348 3349 /* 3350 * Look for additional filtering rules among the ancestors. 3351 */ 3352 if (VBoxGuiStatsFilterData::s_cInstances > 0 /* quick & dirty optimization */) 3353 { 3354 VBoxGuiStatsFilterData const *pFilter = pParent->pFilter; 3355 while (!pFilter && (pParent = pParent->pParent) != NULL) 3356 pFilter = pParent->pFilter; 3357 if (pFilter) 3358 { 3359 if (pFilter->uMinValue > 0 || pFilter->uMaxValue != UINT64_MAX) 3360 { 3361 uint64_t const uValue = VBoxDbgStatsModel::getValueTimesAsUInt(pNode); 3362 if ( uValue < pFilter->uMinValue 3363 || uValue > pFilter->uMaxValue) 3364 return false; 3365 } 3366 if (pFilter->pRegexName) 3367 { 3368 if (!pFilter->pRegexName->match(pNode->pszName).hasMatch()) 3369 return false; 3370 } 3146 3371 } 3147 3372 } … … 3212 3437 3213 3438 3439 void 3440 VBoxDbgStatsSortFileProxyModel::notifyFilterChanges() 3441 { 3442 invalidateRowsFilter(); 3443 } 3444 3445 3214 3446 #endif /* VBOXDBG_WITH_SORTED_AND_FILTERED_STATS */ 3215 3447 … … 3265 3497 * Create and setup the actions. 3266 3498 */ 3267 m_pExpandAct = new QAction("Expand Tree", this); 3268 m_pCollapseAct = new QAction("Collapse Tree", this); 3269 m_pRefreshAct = new QAction("&Refresh", this); 3270 m_pResetAct = new QAction("Rese&t", this); 3271 m_pCopyAct = new QAction("&Copy", this); 3272 m_pToLogAct = new QAction("To &Log", this); 3273 m_pToRelLogAct = new QAction("T&o Release Log", this); 3274 m_pAdjColumns = new QAction("&Adjust Columns", this); 3499 m_pExpandAct = new QAction("Expand Tree", this); 3500 m_pCollapseAct = new QAction("Collapse Tree", this); 3501 m_pRefreshAct = new QAction("&Refresh", this); 3502 m_pResetAct = new QAction("Rese&t", this); 3503 m_pCopyAct = new QAction("&Copy", this); 3504 m_pToLogAct = new QAction("To &Log", this); 3505 m_pToRelLogAct = new QAction("T&o Release Log", this); 3506 m_pAdjColumnsAct = new QAction("&Adjust Columns", this); 3507 #ifdef VBOXDBG_WITH_SORTED_AND_FILTERED_STATS 3508 m_pFilterAct = new QAction("&Filter...", this); 3509 #endif 3275 3510 3276 3511 m_pCopyAct->setShortcut(QKeySequence::Copy); … … 3281 3516 m_pToLogAct->setShortcut(QKeySequence("Ctrl+Z")); 3282 3517 m_pToRelLogAct->setShortcut(QKeySequence("Alt+Z")); 3283 m_pAdjColumns->setShortcut(QKeySequence("Ctrl+A")); 3518 m_pAdjColumnsAct->setShortcut(QKeySequence("Ctrl+A")); 3519 #ifdef VBOXDBG_WITH_SORTED_AND_FILTERED_STATS 3520 //m_pFilterAct->setShortcut(QKeySequence("Ctrl+?")); 3521 #endif 3284 3522 3285 3523 addAction(m_pCopyAct); … … 3290 3528 addAction(m_pToLogAct); 3291 3529 addAction(m_pToRelLogAct); 3292 addAction(m_pAdjColumns); 3293 3294 connect(m_pExpandAct, SIGNAL(triggered(bool)), this, SLOT(actExpand())); 3295 connect(m_pCollapseAct, SIGNAL(triggered(bool)), this, SLOT(actCollapse())); 3296 connect(m_pRefreshAct, SIGNAL(triggered(bool)), this, SLOT(actRefresh())); 3297 connect(m_pResetAct, SIGNAL(triggered(bool)), this, SLOT(actReset())); 3298 connect(m_pCopyAct, SIGNAL(triggered(bool)), this, SLOT(actCopy())); 3299 connect(m_pToLogAct, SIGNAL(triggered(bool)), this, SLOT(actToLog())); 3300 connect(m_pToRelLogAct, SIGNAL(triggered(bool)), this, SLOT(actToRelLog())); 3301 connect(m_pAdjColumns, SIGNAL(triggered(bool)), this, SLOT(actAdjColumns())); 3530 addAction(m_pAdjColumnsAct); 3531 #ifdef VBOXDBG_WITH_SORTED_AND_FILTERED_STATS 3532 addAction(m_pFilterAct); 3533 #endif 3534 3535 connect(m_pExpandAct, SIGNAL(triggered(bool)), this, SLOT(actExpand())); 3536 connect(m_pCollapseAct, SIGNAL(triggered(bool)), this, SLOT(actCollapse())); 3537 connect(m_pRefreshAct, SIGNAL(triggered(bool)), this, SLOT(actRefresh())); 3538 connect(m_pResetAct, SIGNAL(triggered(bool)), this, SLOT(actReset())); 3539 connect(m_pCopyAct, SIGNAL(triggered(bool)), this, SLOT(actCopy())); 3540 connect(m_pToLogAct, SIGNAL(triggered(bool)), this, SLOT(actToLog())); 3541 connect(m_pToRelLogAct, SIGNAL(triggered(bool)), this, SLOT(actToRelLog())); 3542 connect(m_pAdjColumnsAct, SIGNAL(triggered(bool)), this, SLOT(actAdjColumns())); 3543 #ifdef VBOXDBG_WITH_SORTED_AND_FILTERED_STATS 3544 connect(m_pFilterAct, SIGNAL(triggered(bool)), this, SLOT(actFilter())); 3545 #endif 3302 3546 3303 3547 … … 3323 3567 m_pBranchMenu->addAction(m_pExpandAct); 3324 3568 m_pBranchMenu->addAction(m_pCollapseAct); 3569 #ifdef VBOXDBG_WITH_SORTED_AND_FILTERED_STATS 3570 m_pBranchMenu->addSeparator(); 3571 m_pBranchMenu->addAction(m_pFilterAct); 3572 #endif 3325 3573 3326 3574 m_pViewMenu = new QMenu(); … … 3334 3582 m_pViewMenu->addAction(m_pCollapseAct); 3335 3583 m_pViewMenu->addSeparator(); 3336 m_pViewMenu->addAction(m_pAdjColumns); 3584 m_pViewMenu->addAction(m_pAdjColumnsAct); 3585 #ifdef VBOXDBG_WITH_SORTED_AND_FILTERED_STATS 3586 m_pViewMenu->addAction(m_pFilterAct); 3587 #endif 3337 3588 3338 3589 /* the header menu */ … … 3364 3615 DELETE_IT(m_pToLogAct); 3365 3616 DELETE_IT(m_pToRelLogAct); 3366 DELETE_IT(m_pAdjColumns); 3617 DELETE_IT(m_pAdjColumnsAct); 3618 DELETE_IT(m_pFilterAct); 3367 3619 #undef DELETE_IT 3368 3620 } … … 3617 3869 } 3618 3870 3871 3872 void 3873 VBoxDbgStatsView::actFilter() 3874 { 3875 #ifdef VBOXDBG_WITH_SORTED_AND_FILTERED_STATS 3876 /* 3877 * Get the node it applies to. 3878 */ 3879 QModelIndex Idx = m_pCurMenu ? m_CurIndex : currentIndex(); 3880 if (Idx.isValid()) 3881 Idx == myGetRootIndex(); 3882 Idx = m_pProxyModel->mapToSource(Idx); 3883 PDBGGUISTATSNODE pNode = m_pVBoxModel->nodeFromIndex(Idx); 3884 if (pNode) 3885 { 3886 /* 3887 * Display dialog (modal). 3888 */ 3889 VBoxDbgStatsFilterDialog Dialog(this, pNode); 3890 if (Dialog.exec() == QDialog::Accepted) 3891 { 3892 /** @todo it is possible that pNode is invalid now! */ 3893 VBoxGuiStatsFilterData * const pOldFilter = pNode->pFilter; 3894 pNode->pFilter = Dialog.dupFilterData(); 3895 if (pOldFilter) 3896 delete pOldFilter; 3897 m_pProxyModel->notifyFilterChanges(); 3898 } 3899 } 3900 #endif 3901 } 3902 3903 3904 3905 3906 3907 3908 /* 3909 * 3910 * V B o x D b g S t a t s F i l t e r D i a l o g 3911 * V B o x D b g S t a t s F i l t e r D i a l o g 3912 * V B o x D b g S t a t s F i l t e r D i a l o g 3913 * 3914 * 3915 */ 3916 3917 /* static */ QRegularExpression const VBoxDbgStatsFilterDialog::s_UInt64ValidatorRegExp("^([0-9]*|0[Xx][0-9a-fA-F]*)$"); 3918 3919 3920 /*static*/ QLineEdit * 3921 VBoxDbgStatsFilterDialog::createUInt64LineEdit(uint64_t uValue) 3922 { 3923 QLineEdit *pRet = new QLineEdit; 3924 if (uValue == 0 || uValue == UINT64_MAX) 3925 pRet->setText(""); 3926 else 3927 pRet->setText(QString().number(uValue)); 3928 pRet->setValidator(new QRegularExpressionValidator(s_UInt64ValidatorRegExp)); 3929 return pRet; 3930 } 3931 3932 3933 VBoxDbgStatsFilterDialog::VBoxDbgStatsFilterDialog(QWidget *a_pParent, PCDBGGUISTATSNODE a_pNode) 3934 : QDialog(a_pParent) 3935 { 3936 /* Set the window title. */ 3937 static char s_szTitlePfx[] = "Filtering - "; 3938 char szTitle[1024 + 128]; 3939 memcpy(szTitle, s_szTitlePfx, sizeof(s_szTitlePfx)); 3940 VBoxDbgStatsModel::getNodePath(a_pNode, &szTitle[sizeof(s_szTitlePfx) - 1], sizeof(szTitle) - sizeof(s_szTitlePfx)); 3941 setWindowTitle(szTitle); 3942 3943 3944 /* Copy the old data if any. */ 3945 VBoxGuiStatsFilterData const * const pOldFilter = a_pNode->pFilter; 3946 if (pOldFilter) 3947 { 3948 m_Data.uMinValue = pOldFilter->uMinValue; 3949 m_Data.uMaxValue = pOldFilter->uMaxValue; 3950 if (pOldFilter->pRegexName) 3951 m_Data.pRegexName = new QRegularExpression(*pOldFilter->pRegexName); 3952 } 3953 3954 /* Configure the dialog... */ 3955 QVBoxLayout *pMainLayout = new QVBoxLayout(this); 3956 3957 /* The value / average range: */ 3958 QGroupBox *pValueAvgGrpBox = new QGroupBox("Value / Average"); 3959 QGridLayout *pValAvgLayout = new QGridLayout; 3960 QLabel *pLabel = new QLabel("Min"); 3961 m_pValueAvgMin = createUInt64LineEdit(m_Data.uMinValue); 3962 pLabel->setBuddy(m_pValueAvgMin); 3963 pValAvgLayout->addWidget(pLabel, 0, 0); 3964 pValAvgLayout->addWidget(m_pValueAvgMin, 0, 1); 3965 3966 pLabel = new QLabel("Max"); 3967 m_pValueAvgMax = createUInt64LineEdit(m_Data.uMaxValue); 3968 pLabel->setBuddy(m_pValueAvgMax); 3969 pValAvgLayout->addWidget(pLabel, 1, 0); 3970 pValAvgLayout->addWidget(m_pValueAvgMax, 1, 1); 3971 3972 pValueAvgGrpBox->setLayout(pValAvgLayout); 3973 pMainLayout->addWidget(pValueAvgGrpBox); 3974 3975 /* The name filter. */ 3976 QGroupBox *pNameGrpBox = new QGroupBox("Name RegExp"); 3977 QHBoxLayout *pNameLayout = new QHBoxLayout(); 3978 m_pNameRegExp = new QLineEdit; 3979 if (m_Data.pRegexName) 3980 m_pNameRegExp->setText(m_Data.pRegexName->pattern()); 3981 else 3982 m_pNameRegExp->setText(""); 3983 m_pNameRegExp->setToolTip("Regular expression matching basenames (no parent) to show."); 3984 pNameLayout->addWidget(m_pNameRegExp); 3985 pNameGrpBox->setLayout(pNameLayout); 3986 pMainLayout->addWidget(pNameGrpBox); 3987 3988 /* Buttons. */ 3989 QDialogButtonBox *pButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this); 3990 pButtonBox->button(QDialogButtonBox::Ok)->setDefault(true); 3991 connect(pButtonBox, &QDialogButtonBox::rejected, this, &VBoxDbgStatsFilterDialog::reject); 3992 connect(pButtonBox, &QDialogButtonBox::accepted, this, &VBoxDbgStatsFilterDialog::validateAndAccept); 3993 pMainLayout->addWidget(pButtonBox); 3994 } 3995 3996 3997 VBoxDbgStatsFilterDialog::~VBoxDbgStatsFilterDialog() 3998 { 3999 /* anything? */ 4000 } 4001 4002 4003 VBoxGuiStatsFilterData * 4004 VBoxDbgStatsFilterDialog::dupFilterData(void) const 4005 { 4006 if (m_Data.isAllDefaults()) 4007 return NULL; 4008 VBoxGuiStatsFilterData *pRet = new VBoxGuiStatsFilterData(); 4009 pRet->uMinValue = m_Data.uMinValue; 4010 pRet->uMaxValue = m_Data.uMaxValue; 4011 if (m_Data.pRegexName) 4012 pRet->pRegexName = new QRegularExpression(*m_Data.pRegexName); 4013 return pRet; 4014 } 4015 4016 4017 uint64_t 4018 VBoxDbgStatsFilterDialog::validateUInt64Field(QLineEdit const *a_pField, uint64_t a_uDefault, 4019 const char *a_pszField, QStringList *a_pLstErrors) 4020 { 4021 QString Str = a_pField->text().trimmed(); 4022 if (!Str.isEmpty()) 4023 { 4024 QByteArray const StrAsUtf8 = Str.toUtf8(); 4025 const char * const pszString = StrAsUtf8.constData(); 4026 uint64_t uValue = a_uDefault; 4027 int vrc = RTStrToUInt64Full(pszString, 0, &uValue); 4028 if (vrc == VINF_SUCCESS) 4029 return uValue; 4030 char szMsg[128]; 4031 RTStrPrintf(szMsg, sizeof(szMsg), "Invalid %s value: %Rrc - ", a_pszField, vrc); 4032 a_pLstErrors->append(QString(szMsg) + Str); 4033 } 4034 4035 return a_uDefault; 4036 } 4037 4038 4039 void 4040 VBoxDbgStatsFilterDialog::validateAndAccept() 4041 { 4042 QStringList LstErrors; 4043 4044 /* The numeric fields. */ 4045 m_Data.uMinValue = validateUInt64Field(m_pValueAvgMin, 0, "minimum value/avg", &LstErrors); 4046 m_Data.uMaxValue = validateUInt64Field(m_pValueAvgMax, UINT64_MAX, "maximum value/avg", &LstErrors); 4047 4048 /* The name regexp. */ 4049 QString Str = m_pNameRegExp->text().trimmed(); 4050 if (!Str.isEmpty()) 4051 { 4052 if (!m_Data.pRegexName) 4053 m_Data.pRegexName = new QRegularExpression(); 4054 m_Data.pRegexName->setPattern(Str); 4055 if (!m_Data.pRegexName->isValid()) 4056 LstErrors.append("Invalid regular expression"); 4057 } 4058 else if (m_Data.pRegexName) 4059 { 4060 delete m_Data.pRegexName; 4061 m_Data.pRegexName = NULL; 4062 } 4063 4064 /* Dismiss the dialog if everything is fine, otherwise complain and keep it open. */ 4065 if (LstErrors.isEmpty()) 4066 emit accept(); 4067 else 4068 { 4069 QMessageBox MsgBox(QMessageBox::Critical, "Invalid input", LstErrors.join("\n"), QMessageBox::Ok); 4070 MsgBox.exec(); 4071 } 4072 } 3619 4073 3620 4074 … … 3818 4272 #endif 3819 4273 } 4274 -
trunk/src/VBox/Debugger/VBoxDbgStatsQt.h
r103403 r103460 161 161 void actToRelLog(); 162 162 void actAdjColumns(); 163 void actFilter(); 163 164 /** @} */ 164 165 … … 204 205 QAction *m_pToRelLogAct; 205 206 /** Adjust the columns. */ 206 QAction *m_pAdjColumns; 207 QAction *m_pAdjColumnsAct; 208 /** Filter sub-tree action. */ 209 QAction *m_pFilterAct; 207 210 #if 0 208 211 /** Save Tree (to file) action. */
Note:
See TracChangeset
for help on using the changeset viewer.