Changeset 12660 in vbox for trunk/src/VBox/Debugger/VBoxDbgStatsQt4.cpp
- Timestamp:
- Sep 22, 2008 11:57:52 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/VBoxDbgStatsQt4.cpp
r12521 r12660 140 140 /** The name. */ 141 141 char *pszName; 142 /** The length of the name. */ 143 size_t cchName; 142 144 /** The description string. */ 143 145 QString *pDescStr; … … 348 350 * 349 351 * @param a_pVM The VM handle. 352 * @param a_rPatStr The selection pattern. 350 353 * @param a_pParent The parent object. NULL is fine. 351 354 */ 352 VBoxDbgStatsModelVM(PVM a_pVM, Q Object *a_pParent);355 VBoxDbgStatsModelVM(PVM a_pVM, QString &a_rPatStr, QObject *a_pParent); 353 356 354 357 /** Destructor */ … … 364 367 virtual void update(const QString &a_rPatStr); 365 368 366 pr ivate:369 protected: 367 370 /** 368 371 * Enumeration callback used by update. … … 387 390 * @returns Pointer to the root of the tree we've constructed. This will be NULL 388 391 * if the STAM API throws an error or we run out of memory. 389 */ 390 PDBGGUISTATSNODE createNewTree(void); 392 * @param a_rPatStr The selection pattern. 393 */ 394 PDBGGUISTATSNODE createNewTree(QString &a_rPatStr); 395 396 protected: 397 /** Next update child. This is UINT32_MAX when invalid. */ 398 uint32_t m_iUpdateChild; 399 /** Pointer to the node m_szUpdateParent represent and m_iUpdateChild refers to. */ 400 PDBGGUISTATSNODE m_pUpdateParent; 401 /** The length of the path. */ 402 size_t m_cchUpdateParent; 403 /** The path to the current update parent, including a trailing slash. */ 404 char m_szUpdateParent[1024]; 405 /** Inserted or/and removed nodes during the update. */ 406 bool m_fUpdateInsertRemove; 391 407 }; 392 408 … … 421 437 422 438 439 #if 0 423 440 /** 424 441 * Formats a number into a 64-byte buffer. … … 448 465 return psz; 449 466 } 467 #endif 450 468 451 469 … … 625 643 pRoot->enmUnit = STAMUNIT_INVALID; 626 644 pRoot->pszName = (char *)RTMemDup("/", sizeof("/")); 645 pRoot->cchName = 1; 627 646 pRoot->enmState = kDbgGuiStatsNodeState_kRoot; 628 647 … … 644 663 pNode->enmUnit = STAMUNIT_INVALID; 645 664 pNode->pszName = (char *)RTMemDupEx(pszName, cchName, 1); 665 pNode->cchName = cchName; 646 666 pNode->enmState = kDbgGuiStatsNodeState_kVisible; 647 667 … … 1061 1081 1062 1082 1063 VBoxDbgStatsModelVM::VBoxDbgStatsModelVM(PVM a_pVM, QObject *a_pParent) 1064 : VBoxDbgStatsModel(a_pParent), VBoxDbgBase(a_pVM) 1065 { 1066 /* 1067 * Create a model containing *all* the STAM entries since this is is 1068 * faster than adding stuff later. (And who cares about wasing a few MBs anyway...) 1069 */ 1070 PDBGGUISTATSNODE pTree = createNewTree(); 1083 VBoxDbgStatsModelVM::VBoxDbgStatsModelVM(PVM a_pVM, QString &a_rPatStr, QObject *a_pParent) 1084 : VBoxDbgStatsModel(a_pParent), VBoxDbgBase(a_pVM), 1085 m_iUpdateChild(UINT32_MAX), m_pUpdateParent(NULL), m_cchUpdateParent(0) 1086 { 1087 /* 1088 * Create a model containing the STAM entries matching the pattern. 1089 * (The original idea was to get everything and rely on some hide/visible 1090 * flag that it turned out didn't exist.) 1091 */ 1092 PDBGGUISTATSNODE pTree = createNewTree(a_rPatStr); 1071 1093 setRootNode(pTree); 1072 1094 } … … 1076 1098 { 1077 1099 /* nothing to do here. */ 1100 } 1101 1102 1103 static void resetNode(PDBGGUISTATSNODE pNode) 1104 { 1105 /** @todo */ 1106 } 1107 1108 static void updateNode(PDBGGUISTATSNODE pNode, STAMTYPE enmType, void *pvSample, STAMUNIT enmUnit, 1109 STAMVISIBILITY enmVisibility, const char *pszDesc, void *pvUser) 1110 { 1111 /** @todo */ 1112 } 1113 1114 static int32_t getNodePath(PCDBGGUISTATSNODE pNode, char *psz, ssize_t cch) 1115 { 1116 int32_t off; 1117 if (!pNode->pParent) 1118 { 1119 /* root - don't add it's slash! */ 1120 AssertReturn(cch >= 1, -1); 1121 off = 0; 1122 *psz = '\0'; 1123 } 1124 else 1125 { 1126 cch -= pNode->cchName - 1; 1127 AssertReturn(cch > 0, -1); 1128 off = getNodePath(pNode->pParent, psz, cch); 1129 if (off >= 0) 1130 { 1131 psz[off++] = '/'; 1132 memcpy(&psz[off], pNode->pszName, pNode->cchName + 1); 1133 off += pNode->cchName; 1134 } 1135 } 1136 return off; 1137 } 1138 1139 static bool isNodeAncestorOf(PCDBGGUISTATSNODE pNode, PCDBGGUISTATSNODE pAncestor) 1140 { 1141 while (pNode) 1142 { 1143 pNode = pNode->pParent; 1144 if (pNode == pAncestor) 1145 return true; 1146 } 1147 return false; 1148 } 1149 1150 static PDBGGUISTATSNODE nextNode(PDBGGUISTATSNODE pNode) 1151 { 1152 /** @todo */ 1153 return pNode; 1154 } 1155 1156 static PDBGGUISTATSNODE prevNode(PDBGGUISTATSNODE pNode) 1157 { 1158 /** @todo */ 1159 return pNode; 1160 } 1161 1162 static void removeAndDeleteNode(PDBGGUISTATSNODE pNode) 1163 { 1164 /** @todo */ 1165 1078 1166 } 1079 1167 … … 1092 1180 return 0; 1093 1181 1094 /** @todo a much much faster approach would be to link all items into a doubly chained list. */ 1095 #if 0 1096 /* 1097 * Locate the node in the tree, creating whatever doesn't exist. 1098 * Because of strict input ordering we can assume that any parent that is 1099 * still in an undetermined state should be wing clipped and show no data. 1100 */ 1101 AssertReturn(*pszName == '/' && pszName[1] != '/', VERR_INTERNAL_ERROR); 1102 PDBGGUISTATSNODE pNode = pRoot; 1103 const char *pszCur = pszName + 1; 1104 while (*pszCur) 1105 { 1106 /* find the end of this component. */ 1107 const char *pszNext = strchr(pszCur, '/'); 1108 if (!pszNext) 1109 pszNext = strchr(pszCur, '\0'); 1110 size_t cchCur = pszNext - pszCur; 1111 1112 /* look it up, create it if it not found. */ 1113 1114 1115 /* Create it if it doesn't exist (it will be last if it exists). */ 1116 if ( !pNode->cChildren 1117 || strncmp(pNode->papChildren[pNode->cChildren - 1]->pszName, pszCur, cchCur) 1118 || pNode->papChildren[pNode->cChildren - 1]->pszName[cchCur]) 1119 { 1120 pNode = createAndInsertNode(pNode, pszCur, pszNext - pszCur, UINT32_MAX); 1121 if (!pNode) 1122 return VERR_NO_MEMORY; 1123 } 1182 /* 1183 * The default assumption is that nothing has changed. 1184 * For now we'll reset the model when ever something changes. 1185 */ 1186 PDBGGUISTATSNODE pNode; 1187 if (pThis->m_iUpdateChild != UINT32_MAX) 1188 { 1189 pNode = pThis->m_pUpdateParent->papChildren[pThis->m_iUpdateChild]; 1190 if ( !strncmp(pszName, pThis->m_szUpdateParent, pThis->m_cchUpdateParent) 1191 && !strcmp(pszName + pThis->m_cchUpdateParent, pNode->pszName)) 1192 /* got it! */; 1124 1193 else 1125 pNode = pNode->papChildren[pNode->cChildren - 1]; 1126 1127 /* Advance */ 1128 pszCur = *pszNext ? pszNext + 1 : pszNext; 1129 } 1130 1131 /* 1132 * Save the data. 1133 */ 1134 return initNode(pNode, enmType, pvSample, enmUnit, enmVisibility, pszDesc); 1135 #endif 1136 #if 0 1137 /* 1138 * Advance to the matching item. 1139 */ 1140 VBoxDbgStatsLeafItem *pCur = pThis->m_pCur; 1141 while (pCur) 1194 { 1195 /* 1196 * We might be inserting a new node between pPrev and pNode 1197 * or we might be removing one or more nodes. Either case is 1198 * handled in the same rough way. 1199 */ 1200 pThis->m_fUpdateInsertRemove = true; 1201 1202 /* Start with the current parent node and look for a common ancestor 1203 hoping that this is faster than going from the root. */ 1204 PDBGGUISTATSNODE const pPrev = prevNode(pNode); 1205 while (pNode != pThis->m_pRoot) 1206 { 1207 if (!strncmp(pszName, pThis->m_szUpdateParent, pThis->m_cchUpdateParent)) 1208 break; 1209 Assert(pThis->m_cchUpdateParent > pNode->cchName); 1210 pThis->m_cchUpdateParent -= pNode->cchName + 1; 1211 pThis->m_szUpdateParent[pThis->m_cchUpdateParent] = '\0'; 1212 pNode = pNode->pParent; 1213 } 1214 1215 /* Decent until we've found/created the node pszName indicates, 1216 modifying m_szUpdateParent as we go along. */ 1217 while (pszName[pThis->m_cchUpdateParent - 1] == '/') 1218 { 1219 /* Find the end of this component. */ 1220 const char *pszStart = &pszName[pThis->m_cchUpdateParent]; 1221 const char *pszEnd = strchr(pszStart, '/'); 1222 if (!pszEnd) 1223 pszEnd = strchr(pszStart, '/'); 1224 char *pszSubName = &pThis->m_szUpdateParent[pThis->m_cchUpdateParent]; 1225 size_t cchSubName = pszEnd - pszStart; 1226 1227 /* Add the name to the path. */ 1228 memcpy(pszSubName, pszStart, cchSubName); 1229 pThis->m_cchUpdateParent += cchSubName; 1230 pThis->m_szUpdateParent[pThis->m_cchUpdateParent] = '\0'; 1231 1232 if (pNode->cChildren) 1233 { 1234 /* first child */ 1235 pNode = createAndInsertNode(pNode, pszSubName, UINT32_MAX); 1236 AssertReturn(pNode, VERR_NO_MEMORY); 1237 } 1238 else 1239 { 1240 /* binary search. */ 1241 int32_t iStart = 0; 1242 int32_t iLast = pNode->cChildren - 1; 1243 for (;;) 1244 { 1245 int32_t i = iStart + (iLast + 1 - iStart) / 2; 1246 int iDiff = strcmp(pszSubName, pNode->papChildren[i]->pszName); 1247 if (iDiff > 0) 1248 { 1249 iStart = i + 1; 1250 if (iStart > iLast) 1251 { 1252 pNode = createAndInsertNode(pNode, pszSubName, iStart); 1253 AssertReturn(pNode, VERR_NO_MEMORY); 1254 break; 1255 } 1256 } 1257 else if (iDiff < 0) 1258 { 1259 iLast = i - 1; 1260 if (iLast < iStart) 1261 { 1262 pNode = createAndInsertNode(pNode, pszSubName, i); 1263 AssertReturn(pNode, VERR_NO_MEMORY); 1264 break; 1265 } 1266 } 1267 else 1268 { 1269 pNode = pNode->papChildren[i]; 1270 break; 1271 } 1272 } 1273 } 1274 1275 pThis->m_szUpdateParent[pThis->m_cchUpdateParent++] = '/'; 1276 pThis->m_szUpdateParent[pThis->m_cchUpdateParent] = '\0'; 1277 Assert(pThis->m_cchUpdateParent < sizeof(pThis->m_szUpdateParent)); 1278 } 1279 Assert(pszName[pThis->m_cchUpdateParent - 1] == '\0'); 1280 1281 /* Remove all the nodes between pNode and pPrev but keep all 1282 of pNode's ancestors (or it'll get orphaned). */ 1283 PDBGGUISTATSNODE pCur = prevNode(pNode); 1284 Assert(pCur != pPrev); 1285 while (pCur != pPrev) 1286 { 1287 PDBGGUISTATSNODE pAdv = prevNode(pCur); 1288 if (!isNodeAncestorOf(pCur, pNode)) 1289 removeAndDeleteNode(pCur); 1290 pCur = pAdv; 1291 } 1292 1293 /* Removed the data from all ancestors of pNode that it doesn't share them pPrev. */ 1294 pCur = pNode->pParent; 1295 while (!isNodeAncestorOf(pCur, pPrev)) 1296 { 1297 resetNode(pNode); 1298 pCur = pCur->pParent; 1299 } 1300 1301 /* Finally, adjust the globals (szUpdateParent is one level too deep). */ 1302 Assert(pThis->m_cchUpdateParent > pNode->cchName - 1); 1303 pThis->m_cchUpdateParent -= pNode->cchName - 1; 1304 pThis->m_szUpdateParent[pThis->m_cchUpdateParent] = '\0'; 1305 pThis->m_pUpdateParent = pNode->pParent; 1306 pThis->m_iUpdateChild = pNode->iSelf; 1307 } 1308 } 1309 else 1142 1310 { 1143 1311 /* 1144 * ASSUMES ascending order of STAM items. 1312 * Insert it at the end of the tree . 1313 * . 1314 * Do the same as we're doing down in createNewTreeCallback, walk from the . 1315 * root and create whatever we need. 1145 1316 */ 1146 int iDiff = strcmp(pszName, pCur->getName()); 1147 if (!iDiff) 1148 break; 1149 if (iDiff > 0) 1150 { 1151 /* 1152 * Removed / filtered out. 1153 */ 1154 Log2(("updateCallback: %s - filtered out\n", pCur->getName())); 1155 if (pCur->isVisible()) 1317 pThis->m_fUpdateInsertRemove = true; 1318 1319 AssertReturn(*pszName == '/' && pszName[1] != '/', VERR_INTERNAL_ERROR); 1320 pNode = pThis->m_pRoot; 1321 const char *pszCur = pszName + 1; 1322 while (*pszCur) 1323 { 1324 /* Find the end of this component. */ 1325 const char *pszNext = strchr(pszCur, '/'); 1326 if (!pszNext) 1327 pszNext = strchr(pszCur, '\0'); 1328 size_t cchCur = pszNext - pszCur; 1329 1330 /* Create it if it doesn't exist (it will be last if it exists). */ 1331 if ( !pNode->cChildren 1332 || strncmp(pNode->papChildren[pNode->cChildren - 1]->pszName, pszCur, cchCur) 1333 || pNode->papChildren[pNode->cChildren - 1]->pszName[cchCur]) 1156 1334 { 1157 pCur->setVisible(false); 1158 hideParentBranches(pCur); 1335 pNode = createAndInsertNode(pNode, pszCur, pszNext - pszCur, UINT32_MAX); 1336 if (!pNode) 1337 return VERR_NO_MEMORY; 1159 1338 } 1160 1161 pCur = pCur->m_pNext;1162 }1163 else if (iDiff < 0)1164 {1165 /*1166 * New item, insert before pCur.1167 */1168 Log2(("updateCallback: %s - new\n", pszName));1169 VBoxDbgStatsLeafItem *pNew = new VBoxDbgStatsLeafItem(pszName, pThis->createPath(pszName));1170 pNew->m_pNext = pCur;1171 pNew->m_pPrev = pCur->m_pPrev;1172 if (pNew->m_pPrev)1173 pNew->m_pPrev->m_pNext = pNew;1174 1339 else 1175 pThis->m_pHead = pNew; 1176 pCur->m_pPrev = pNew; 1177 pCur = pNew; 1178 Assert(!strcmp(pszName, pCur->getName())); 1179 break; 1180 } 1181 } 1182 1183 /* 1184 * End of items, insert it at the tail. 1185 */ 1186 if (!pCur) 1187 { 1188 Log2(("updateCallback: %s - new end\n", pszName)); 1189 pCur = new VBoxDbgStatsLeafItem(pszName, pThis->createPath(pszName)); 1190 pCur->m_pNext = NULL; 1191 pCur->m_pPrev = pThis->m_pTail; 1192 if (pCur->m_pPrev) 1193 pCur->m_pPrev->m_pNext = pCur; 1194 else 1195 pThis->m_pHead = pCur; 1196 pThis->m_pTail = pCur; 1197 } 1198 Assert(pThis->m_pHead); 1199 Assert(pThis->m_pTail); 1200 1201 /* 1202 * Update it and move on. 1203 */ 1204 if (!pCur->isVisible()) 1205 showParentBranches(pCur); 1206 pCur->update(enmType, pvSample, enmUnit, enmVisibility, pszDesc); 1207 pThis->m_pCur = pCur->m_pNext; 1208 1209 #endif 1340 pNode = pNode->papChildren[pNode->cChildren - 1]; 1341 1342 /* Advance */ 1343 pszCur = *pszNext ? pszNext + 1 : pszNext; 1344 } 1345 1346 } 1347 1348 /* 1349 * Perform the update. 1350 */ 1351 updateNode(pNode, enmType, pvSample, enmUnit, enmVisibility, pszDesc, pvUser); 1352 1353 /* 1354 * Advance to the next node. 1355 * (Again, we're ASSUMING that the input is sorted on (full) path name.) 1356 */ 1357 PDBGGUISTATSNODE pParent = pNode->pParent; 1358 if (pNode->cChildren) 1359 { 1360 /* decend to the children. */ 1361 pThis->m_iUpdateChild = 0; 1362 Assert(pThis->m_cchUpdateParent + pNode->cchName + 2 < sizeof(pThis->m_szUpdateParent)); 1363 memcpy(&pThis->m_szUpdateParent[pThis->m_cchUpdateParent], pNode->pszName, pNode->cchName); 1364 pThis->m_cchUpdateParent += pNode->cchName; 1365 pThis->m_szUpdateParent[pThis->m_cchUpdateParent++] = '/'; 1366 pThis->m_pUpdateParent = pNode; 1367 } 1368 else if (pNode->iSelf + 1 < pParent->cChildren) 1369 { 1370 /* next sibling */ 1371 pThis->m_iUpdateChild = pNode->iSelf + 1; 1372 Assert(pThis->m_pUpdateParent == pNode->pParent); 1373 } 1374 else 1375 { 1376 /* move up and down- / on-wards */ 1377 for (;;) 1378 { 1379 /* ascend */ 1380 pNode = pParent; 1381 pParent = pParent->pParent; 1382 if (!pParent) 1383 { 1384 Assert(pNode == pThis->m_pRoot); 1385 pThis->m_iUpdateChild = UINT32_MAX; 1386 pThis->m_szUpdateParent[0] = '\0'; 1387 pThis->m_cchUpdateParent = 0; 1388 pThis->m_pUpdateParent = NULL; 1389 break; 1390 } 1391 Assert(pThis->m_cchUpdateParent > pNode->cchName); 1392 pThis->m_cchUpdateParent -= pNode->cchName - 1; 1393 pThis->m_szUpdateParent[pThis->m_cchUpdateParent] = '\0'; 1394 1395 /* try advance */ 1396 if (pNode->iSelf + 1 < pParent->cChildren) 1397 { 1398 pNode = pParent->papChildren[pNode->iSelf + 1]; 1399 1400 /* decend to a node containing data. */ 1401 while ( pNode->enmType == STAMTYPE_INVALID 1402 && pNode->cChildren > 0) 1403 { 1404 Assert(pNode->enmState == kDbgGuiStatsNodeState_kVisible); 1405 1406 Assert(pThis->m_cchUpdateParent + pNode->cchName + 2 < sizeof(pThis->m_szUpdateParent)); 1407 memcpy(&pThis->m_szUpdateParent[pThis->m_cchUpdateParent], pNode->pszName, pNode->cchName); 1408 pThis->m_cchUpdateParent += pNode->cchName; 1409 pThis->m_szUpdateParent[pThis->m_cchUpdateParent++] = '/'; 1410 1411 pNode = pNode->papChildren[0]; 1412 } 1413 Assert(pNode->enmType != STAMTYPE_INVALID); 1414 pThis->m_iUpdateChild = pNode->iSelf; 1415 pThis->m_pUpdateParent = pNode->pParent; 1416 break; 1417 } 1418 } 1419 1420 } 1210 1421 return VINF_SUCCESS; 1211 1422 } … … 1216 1427 { 1217 1428 /* 1218 * Mark all nodes that aren't yet invisble as invisible. 1219 * (Depth first) 1220 */ 1221 DBGGUISTATSSTACK Stack; 1222 Stack.a[0].pNode = m_pRoot; 1223 Stack.a[0].iChild = -1; 1224 Stack.iTop = 0; 1225 1226 while (Stack.iTop >= 0) 1227 { 1228 /* get top element */ 1229 PDBGGUISTATSNODE pNode = Stack.a[Stack.iTop].pNode; 1230 uint32_t iChild = ++Stack.a[Stack.iTop].iChild; 1231 if (iChild < pNode->cChildren) 1232 { 1233 /* push */ 1234 Stack.iTop++; 1235 Assert(Stack.iTop < (int32_t)RT_ELEMENTS(Stack.a)); 1236 Stack.a[Stack.iTop].pNode = pNode->papChildren[iChild]; 1237 Stack.a[Stack.iTop].iChild = 0; 1238 } 1239 else 1240 { 1241 /* pop */ 1242 Stack.iTop--; 1243 1244 /* do the actual work. */ 1245 switch (pNode->enmState) 1429 * Find the first child with data and set it up as the 'next' 1430 * node to be updated. 1431 */ 1432 PDBGGUISTATSNODE pFirst = m_pRoot; 1433 while (pFirst && pFirst->enmType == STAMTYPE_INVALID) 1434 pFirst = nextNode(pFirst); 1435 if (pFirst) 1436 { 1437 m_iUpdateChild = pFirst->iSelf; 1438 m_pUpdateParent = pFirst; 1439 m_cchUpdateParent = getNodePath(m_pUpdateParent, m_szUpdateParent, sizeof(m_szUpdateParent) - 1); 1440 AssertReturnVoid(m_cchUpdateParent >= 1); 1441 m_szUpdateParent[m_cchUpdateParent++] = '/'; 1442 m_szUpdateParent[m_cchUpdateParent] = '\0'; 1443 } 1444 else 1445 { 1446 m_iUpdateChild = UINT32_MAX; 1447 m_pUpdateParent = NULL; 1448 m_szUpdateParent[0] = '\0'; 1449 m_cchUpdateParent = 0; 1450 } 1451 1452 /* 1453 * Perform the update. 1454 * 1455 * If we're inserting and/or removing anything we'll simply reset the model. 1456 * This can be optimized later when the normal updating is working perfectly. 1457 */ 1458 m_fUpdateInsertRemove = false; 1459 1460 /** @todo the way we update this stuff is independent of the source (XML, file, STAM), our only 1461 * ASSUMPTION is that the input is strictly ordered by (full) name. So, all this stuff should 1462 * really move up into the parent class. */ 1463 stamEnum(a_rPatStr, updateCallback, this); 1464 1465 if (m_fUpdateInsertRemove) 1466 reset(); 1467 else 1468 { 1469 /* 1470 * Send dataChanged events. 1471 */ 1472 DBGGUISTATSSTACK Stack; 1473 Stack.a[0].pNode = m_pRoot; 1474 Stack.a[0].iChild = -1; 1475 Stack.iTop = 0; 1476 1477 while (Stack.iTop >= 0) 1478 { 1479 /* get top element */ 1480 PDBGGUISTATSNODE pNode = Stack.a[Stack.iTop].pNode; 1481 uint32_t iChild = ++Stack.a[Stack.iTop].iChild; 1482 if (iChild < pNode->cChildren) 1246 1483 { 1247 case kDbgGuiStatsNodeState_kVisible: 1248 pNode->enmState = kDbgGuiStatsNodeState_kMakeInvisible; 1249 break; 1250 case kDbgGuiStatsNodeState_kInvisible: 1251 case kDbgGuiStatsNodeState_kRoot: 1252 break; 1253 default: 1254 AssertMsgFailedBreak(("%d\n", pNode->enmState)); 1484 /* push */ 1485 Stack.iTop++; 1486 Assert(Stack.iTop < (int32_t)RT_ELEMENTS(Stack.a)); 1487 Stack.a[Stack.iTop].pNode = pNode->papChildren[iChild]; 1488 Stack.a[Stack.iTop].iChild = 0; 1255 1489 } 1256 } 1257 } 1258 1259 1260 /* 1261 * Perform the update. 1262 */ 1263 stamEnum(a_rPatStr, updateCallback, this); 1264 1265 1266 /* 1267 * Send dataChanged events. 1268 */ 1269 Stack.a[0].pNode = m_pRoot; 1270 Stack.a[0].iChild = -1; 1271 Stack.iTop = 0; 1272 1273 while (Stack.iTop >= 0) 1274 { 1275 /* get top element */ 1276 PDBGGUISTATSNODE pNode = Stack.a[Stack.iTop].pNode; 1277 uint32_t iChild = ++Stack.a[Stack.iTop].iChild; 1278 if (iChild < pNode->cChildren) 1279 { 1280 /* push */ 1281 Stack.iTop++; 1282 Assert(Stack.iTop < (int32_t)RT_ELEMENTS(Stack.a)); 1283 Stack.a[Stack.iTop].pNode = pNode->papChildren[iChild]; 1284 Stack.a[Stack.iTop].iChild = 0; 1285 } 1286 else 1287 { 1288 /* pop */ 1289 Stack.iTop--; 1290 1291 /* do the actual work. */ 1292 iChild = 0; 1293 while (iChild < pNode->cChildren) 1490 else 1294 1491 { 1295 /* skip to the first needing updating. */ 1296 while ( iChild < pNode->cChildren 1297 && ( pNode->papChildren[iChild]->enmState != kDbgGuiStatsNodeState_kMakeVisible 1298 && pNode->papChildren[iChild]->enmState != kDbgGuiStatsNodeState_kMakeInvisible 1299 && pNode->papChildren[iChild]->enmState != kDbgGuiStatsNodeState_kRefresh)) 1300 iChild++; 1301 if (iChild >= pNode->cChildren) 1302 break; 1303 QModelIndex TopLeft = createIndex(iChild, 0, pNode->papChildren[iChild]); 1304 1305 /* collect any subsequent nodes that also needs refreshing. */ 1306 while (++iChild < pNode->cChildren) 1492 /* pop */ 1493 Stack.iTop--; 1494 1495 /* do the actual work. */ 1496 iChild = 0; 1497 while (iChild < pNode->cChildren) 1307 1498 { 1308 DBGGUISTATENODESTATE enmState = pNode->papChildren[iChild]->enmState;1309 if ( enmState == kDbgGuiStatsNodeState_kRefresh1310 || enmState == kDbgGuiStatsNodeState_kMakeVisible)1311 enmState = kDbgGuiStatsNodeState_kVisible;1312 else if (enmState == kDbgGuiStatsNodeState_kMakeInvisible)1313 enmState = kDbgGuiStatsNodeState_kInvisible;1314 else1499 /* skip to the first needing updating. */ 1500 while ( iChild < pNode->cChildren 1501 && ( pNode->papChildren[iChild]->enmState != kDbgGuiStatsNodeState_kMakeVisible 1502 && pNode->papChildren[iChild]->enmState != kDbgGuiStatsNodeState_kMakeInvisible 1503 && pNode->papChildren[iChild]->enmState != kDbgGuiStatsNodeState_kRefresh)) 1504 iChild++; 1505 if (iChild >= pNode->cChildren) 1315 1506 break; 1316 pNode->papChildren[iChild]->enmState = enmState; 1507 QModelIndex TopLeft = createIndex(iChild, 0, pNode->papChildren[iChild]); 1508 1509 /* collect any subsequent nodes that also needs refreshing. */ 1510 while (++iChild < pNode->cChildren) 1511 { 1512 DBGGUISTATENODESTATE enmState = pNode->papChildren[iChild]->enmState; 1513 if ( enmState == kDbgGuiStatsNodeState_kRefresh 1514 || enmState == kDbgGuiStatsNodeState_kMakeVisible) 1515 enmState = kDbgGuiStatsNodeState_kVisible; 1516 else if (enmState == kDbgGuiStatsNodeState_kMakeInvisible) 1517 enmState = kDbgGuiStatsNodeState_kInvisible; 1518 else 1519 break; 1520 pNode->papChildren[iChild]->enmState = enmState; 1521 } 1522 QModelIndex BottomRight = createIndex(iChild - 1, DBGGUI_STATS_COLUMNS - 1, pNode->papChildren[iChild - 1]); 1523 1524 /* emit the refresh signal */ 1525 emit dataChanged(TopLeft, BottomRight); 1317 1526 } 1318 QModelIndex BottomRight = createIndex(iChild - 1, DBGGUI_STATS_COLUMNS - 1, pNode->papChildren[iChild - 1]);1319 1320 /* emit the refresh signal */1321 emit dataChanged(TopLeft, BottomRight);1322 1527 } 1323 1528 } … … 1479 1684 1480 1685 PDBGGUISTATSNODE 1481 VBoxDbgStatsModelVM::createNewTree( void)1686 VBoxDbgStatsModelVM::createNewTree(QString &a_rPatStr) 1482 1687 { 1483 1688 PDBGGUISTATSNODE pRoot = createRootNode(); 1484 1689 if (pRoot) 1485 1690 { 1486 int rc = stamEnum( QString(), createNewTreeCallback, pRoot);1691 int rc = stamEnum(a_rPatStr, createNewTreeCallback, pRoot); 1487 1692 if (VBOX_SUCCESS(rc)) 1488 1693 return pRoot; … … 2327 2532 m_pPatCB = new QComboBox(); 2328 2533 pHLayout->addWidget(m_pPatCB); 2329 if ( pszPat && *pszPat)2330 m_pPatCB->addItem( pszPat);2534 if (!m_PatStr.isEmpty()) 2535 m_pPatCB->addItem(m_PatStr); 2331 2536 m_pPatCB->setDuplicatesEnabled(false); 2332 2537 m_pPatCB->setEditable(true); … … 2359 2564 * Create the tree view and setup the layout. 2360 2565 */ 2361 VBoxDbgStatsModelVM *pModel = new VBoxDbgStatsModelVM(pVM, NULL);2566 VBoxDbgStatsModelVM *pModel = new VBoxDbgStatsModelVM(pVM, m_PatStr, NULL); 2362 2567 m_pView = new VBoxDbgStatsView(pVM, pModel, this); 2363 2568
Note:
See TracChangeset
for help on using the changeset viewer.