1 /* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkDebuggerGUI.h" 9 #include "SkPicture.h" 10 #include <QListWidgetItem> 11 #include <QtGui> 12 #include "sk_tool_utils.h" 13 14 SkDebuggerGUI::SkDebuggerGUI(QWidget *parent) : 15 QMainWindow(parent) 16 , fCentralSplitter(this) 17 , fStatusBar(this) 18 , fToolBar(this) 19 , fActionOpen(this) 20 , fActionBreakpoint(this) 21 , fActionCancel(this) 22 , fActionClearBreakpoints(this) 23 , fActionClearDeletes(this) 24 , fActionClose(this) 25 , fActionCreateBreakpoint(this) 26 , fActionDelete(this) 27 , fActionDirectory(this) 28 , fActionGoToLine(this) 29 , fActionInspector(this) 30 , fActionSettings(this) 31 , fActionPlay(this) 32 , fActionPause(this) 33 , fActionRewind(this) 34 , fActionSave(this) 35 , fActionSaveAs(this) 36 , fActionShowDeletes(this) 37 , fActionStepBack(this) 38 , fActionStepForward(this) 39 , fActionZoomIn(this) 40 , fActionZoomOut(this) 41 , fMapper(this) 42 , fListWidget(&fCentralSplitter) 43 , fDirectoryWidget(&fCentralSplitter) 44 , fCanvasWidget(this, &fDebugger) 45 , fDrawCommandGeometryWidget(&fDebugger) 46 , fMenuBar(this) 47 , fMenuFile(this) 48 , fMenuNavigate(this) 49 , fMenuView(this) 50 , fLoading(false) 51 { 52 setupUi(this); 53 fListWidget.setSelectionMode(QAbstractItemView::ExtendedSelection); 54 connect(&fListWidget, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, 55 SLOT(updateDrawCommandInfo())); 56 connect(&fActionOpen, SIGNAL(triggered()), this, SLOT(openFile())); 57 connect(&fActionDirectory, SIGNAL(triggered()), this, SLOT(toggleDirectory())); 58 connect(&fDirectoryWidget, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), this, SLOT(loadFile(QListWidgetItem *))); 59 connect(&fDirectoryWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(populateDirectoryWidget())); 60 connect(&fActionDelete, SIGNAL(triggered()), this, SLOT(actionDelete())); 61 connect(&fListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(toggleBreakpoint())); 62 connect(&fActionRewind, SIGNAL(triggered()), this, SLOT(actionRewind())); 63 connect(&fActionPlay, SIGNAL(triggered()), this, SLOT(actionPlay())); 64 connect(&fActionStepBack, SIGNAL(triggered()), this, SLOT(actionStepBack())); 65 connect(&fActionStepForward, SIGNAL(triggered()), this, SLOT(actionStepForward())); 66 connect(&fActionBreakpoint, SIGNAL(triggered()), this, SLOT(actionBreakpoints())); 67 connect(&fActionInspector, SIGNAL(triggered()), this, SLOT(actionInspector())); 68 connect(&fActionSettings, SIGNAL(triggered()), this, SLOT(actionSettings())); 69 connect(&fFilter, SIGNAL(activated(QString)), this, SLOT(toggleFilter(QString))); 70 connect(&fActionCancel, SIGNAL(triggered()), this, SLOT(actionCancel())); 71 connect(&fActionClearBreakpoints, SIGNAL(triggered()), this, SLOT(actionClearBreakpoints())); 72 connect(&fActionClearDeletes, SIGNAL(triggered()), this, SLOT(actionClearDeletes())); 73 connect(&fActionClose, SIGNAL(triggered()), this, SLOT(actionClose())); 74 #if SK_SUPPORT_GPU 75 connect(&fSettingsWidget, SIGNAL(glSettingsChanged()), this, SLOT(actionGLSettingsChanged())); 76 #endif 77 connect(&fSettingsWidget, SIGNAL(rasterSettingsChanged()), this, SLOT(actionRasterSettingsChanged())); 78 connect(&fSettingsWidget, SIGNAL(visualizationsChanged()), this, SLOT(actionVisualizationsChanged())); 79 connect(&fSettingsWidget, SIGNAL(texFilterSettingsChanged()), this, SLOT(actionTextureFilter())); 80 connect(&fActionPause, SIGNAL(toggled(bool)), this, SLOT(pauseDrawing(bool))); 81 connect(&fActionCreateBreakpoint, SIGNAL(activated()), this, SLOT(toggleBreakpoint())); 82 connect(&fActionShowDeletes, SIGNAL(triggered()), this, SLOT(showDeletes())); 83 connect(&fCanvasWidget, SIGNAL(hitChanged(int)), this, SLOT(selectCommand(int))); 84 connect(&fCanvasWidget, SIGNAL(hitChanged(int)), this, SLOT(updateHit(int))); 85 connect(&fCanvasWidget, SIGNAL(scaleFactorChanged(float)), this, SLOT(actionScale(float))); 86 87 connect(&fActionSaveAs, SIGNAL(triggered()), this, SLOT(actionSaveAs())); 88 connect(&fActionSave, SIGNAL(triggered()), this, SLOT(actionSave())); 89 90 fMapper.setMapping(&fActionZoomIn, SkCanvasWidget::kIn_ZoomCommand); 91 fMapper.setMapping(&fActionZoomOut, SkCanvasWidget::kOut_ZoomCommand); 92 93 connect(&fActionZoomIn, SIGNAL(triggered()), &fMapper, SLOT(map())); 94 connect(&fActionZoomOut, SIGNAL(triggered()), &fMapper, SLOT(map())); 95 connect(&fMapper, SIGNAL(mapped(int)), &fCanvasWidget, SLOT(zoom(int))); 96 97 fViewStateFrame.setDisabled(true); 98 fInspectorWidget.setDisabled(true); 99 fMenuEdit.setDisabled(true); 100 fMenuNavigate.setDisabled(true); 101 fMenuView.setDisabled(true); 102 } 103 104 void SkDebuggerGUI::actionBreakpoints() { 105 bool breakpointsActivated = fActionBreakpoint.isChecked(); 106 for (int row = 0; row < fListWidget.count(); row++) { 107 QListWidgetItem *item = fListWidget.item(row); 108 item->setHidden(item->checkState() == Qt::Unchecked && breakpointsActivated); 109 } 110 } 111 112 void SkDebuggerGUI::showDeletes() { 113 bool deletesActivated = fActionShowDeletes.isChecked(); 114 for (int row = 0; row < fListWidget.count(); row++) { 115 QListWidgetItem *item = fListWidget.item(row); 116 item->setHidden(fDebugger.isCommandVisible(row) && deletesActivated); 117 } 118 } 119 120 void SkDebuggerGUI::actionCancel() { 121 for (int row = 0; row < fListWidget.count(); row++) { 122 fListWidget.item(row)->setHidden(false); 123 } 124 } 125 126 void SkDebuggerGUI::actionClearBreakpoints() { 127 for (int row = 0; row < fListWidget.count(); row++) { 128 QListWidgetItem* item = fListWidget.item(row); 129 item->setCheckState(Qt::Unchecked); 130 item->setData(Qt::DecorationRole, 131 QPixmap(":/blank.png")); 132 } 133 } 134 135 void SkDebuggerGUI::actionClearDeletes() { 136 for (int row = 0; row < fListWidget.count(); row++) { 137 QListWidgetItem* item = fListWidget.item(row); 138 item->setData(Qt::UserRole + 2, QPixmap(":/blank.png")); 139 fDebugger.setCommandVisible(row, true); 140 fSkipCommands[row] = false; 141 } 142 this->updateImage(); 143 } 144 145 void SkDebuggerGUI::actionClose() { 146 this->close(); 147 } 148 149 void SkDebuggerGUI::actionDelete() { 150 151 for (int row = 0; row < fListWidget.count(); ++row) { 152 QListWidgetItem* item = fListWidget.item(row); 153 154 if (!item->isSelected()) { 155 continue; 156 } 157 158 if (fDebugger.isCommandVisible(row)) { 159 item->setData(Qt::UserRole + 2, QPixmap(":/delete.png")); 160 fDebugger.setCommandVisible(row, false); 161 fSkipCommands[row] = true; 162 } else { 163 item->setData(Qt::UserRole + 2, QPixmap(":/blank.png")); 164 fDebugger.setCommandVisible(row, true); 165 fSkipCommands[row] = false; 166 } 167 } 168 169 this->updateImage(); 170 } 171 172 #if SK_SUPPORT_GPU 173 void SkDebuggerGUI::actionGLSettingsChanged() { 174 bool isToggled = fSettingsWidget.isGLActive(); 175 if (isToggled) { 176 fCanvasWidget.setGLSampleCount(fSettingsWidget.getGLSampleCount()); 177 } 178 fCanvasWidget.setWidgetVisibility(SkCanvasWidget::kGPU_WidgetType, !isToggled); 179 } 180 #endif 181 182 void SkDebuggerGUI::actionInspector() { 183 bool newState = !fInspectorWidget.isHidden(); 184 185 fInspectorWidget.setHidden(newState); 186 fViewStateFrame.setHidden(newState); 187 fDrawCommandGeometryWidget.setHidden(newState); 188 } 189 190 void SkDebuggerGUI::actionPlay() { 191 for (int row = fListWidget.currentRow() + 1; row < fListWidget.count(); 192 row++) { 193 QListWidgetItem *item = fListWidget.item(row); 194 if (item->checkState() == Qt::Checked) { 195 fListWidget.setCurrentItem(item); 196 return; 197 } 198 } 199 fListWidget.setCurrentRow(fListWidget.count() - 1); 200 } 201 202 void SkDebuggerGUI::actionRasterSettingsChanged() { 203 fCanvasWidget.setWidgetVisibility(SkCanvasWidget::kRaster_8888_WidgetType, 204 !fSettingsWidget.isRasterEnabled()); 205 this->updateImage(); 206 } 207 208 void SkDebuggerGUI::actionVisualizationsChanged() { 209 fDebugger.setMegaViz(fSettingsWidget.isMegaVizEnabled()); 210 fDebugger.setPathOps(fSettingsWidget.isPathOpsEnabled()); 211 fDebugger.highlightCurrentCommand(fSettingsWidget.isVisibilityFilterEnabled()); 212 fDebugger.setOverdrawViz(fSettingsWidget.isOverdrawVizEnabled()); 213 this->updateImage(); 214 } 215 216 void SkDebuggerGUI::actionTextureFilter() { 217 SkFilterQuality quality; 218 bool enabled = fSettingsWidget.getFilterOverride(&quality); 219 fDebugger.setTexFilterOverride(enabled, quality); 220 fCanvasWidget.update(); 221 } 222 223 void SkDebuggerGUI::actionRewind() { 224 fListWidget.setCurrentRow(0); 225 } 226 227 void SkDebuggerGUI::actionSave() { 228 fFileName = fPath.toAscii().data(); 229 fFileName.append("/"); 230 fFileName.append(fDirectoryWidget.currentItem()->text().toAscii().data()); 231 saveToFile(fFileName); 232 } 233 234 void SkDebuggerGUI::actionSaveAs() { 235 QString filename = QFileDialog::getSaveFileName(this, "Save File", "", 236 "Skia Picture (*skp)"); 237 if (!filename.endsWith(".skp", Qt::CaseInsensitive)) { 238 filename.append(".skp"); 239 } 240 saveToFile(SkString(filename.toAscii().data())); 241 } 242 243 void SkDebuggerGUI::actionScale(float scaleFactor) { 244 fZoomBox.setText(QString::number(scaleFactor * 100, 'f', 0).append("%")); 245 } 246 247 void SkDebuggerGUI::actionSettings() { 248 if (fSettingsWidget.isHidden()) { 249 fSettingsWidget.setHidden(false); 250 } else { 251 fSettingsWidget.setHidden(true); 252 } 253 } 254 255 void SkDebuggerGUI::actionStepBack() { 256 int currentRow = fListWidget.currentRow(); 257 if (currentRow != 0) { 258 fListWidget.setCurrentRow(currentRow - 1); 259 } 260 } 261 262 void SkDebuggerGUI::actionStepForward() { 263 int currentRow = fListWidget.currentRow(); 264 QString curRow = QString::number(currentRow); 265 QString curCount = QString::number(fListWidget.count()); 266 if (currentRow < fListWidget.count() - 1) { 267 fListWidget.setCurrentRow(currentRow + 1); 268 } 269 } 270 271 void SkDebuggerGUI::drawComplete() { 272 SkString clipStack; 273 fDebugger.getClipStackText(&clipStack); 274 fInspectorWidget.setText(clipStack.c_str(), SkInspectorWidget::kClipStack_TabType); 275 276 fInspectorWidget.setMatrix(fDebugger.getCurrentMatrix()); 277 fInspectorWidget.setClip(fDebugger.getCurrentClip()); 278 } 279 280 void SkDebuggerGUI::saveToFile(const SkString& filename) { 281 SkFILEWStream file(filename.c_str()); 282 sk_sp<SkPicture> copy(fDebugger.copyPicture()); 283 284 sk_sp<SkPixelSerializer> serializer(sk_tool_utils::MakePixelSerializer()); 285 copy->serialize(&file, serializer.get()); 286 } 287 288 void SkDebuggerGUI::loadFile(QListWidgetItem *item) { 289 if (item == nullptr) { 290 return; 291 } 292 293 SkString fileName(fPath.toAscii().data()); 294 // don't add a '/' to files in the local directory 295 if (fileName.size() > 0) { 296 fileName.append("/"); 297 } 298 fileName.append(item->text().toAscii().data()); 299 300 if (!fileName.equals(fFileName)) { 301 fFileName = fileName; 302 loadPicture(fFileName); 303 } 304 } 305 306 void SkDebuggerGUI::openFile() { 307 QString temp = QFileDialog::getOpenFileName(this, tr("Open File"), "", 308 tr("Files (*.*)")); 309 openFile(temp); 310 } 311 312 void SkDebuggerGUI::openFile(const QString &filename) { 313 if (!filename.isEmpty()) { 314 QFileInfo pathInfo(filename); 315 loadPicture(SkString(filename.toAscii().data())); 316 setupDirectoryWidget(pathInfo.path()); 317 } 318 } 319 320 void SkDebuggerGUI::pauseDrawing(bool isPaused) { 321 fPausedRow = fListWidget.currentRow(); 322 this->updateDrawCommandInfo(); 323 } 324 325 void SkDebuggerGUI::updateDrawCommandInfo() { 326 int currentRow = -1; 327 if (!fLoading) { 328 currentRow = fListWidget.currentRow(); 329 } 330 if (currentRow == -1) { 331 fInspectorWidget.setText("", SkInspectorWidget::kDetail_TabType); 332 fInspectorWidget.setText("", SkInspectorWidget::kClipStack_TabType); 333 fCurrentCommandBox.setText(""); 334 fDrawCommandGeometryWidget.setDrawCommandIndex(-1); 335 } else { 336 this->updateImage(); 337 338 const SkTDArray<SkString*> *currInfo = fDebugger.getCommandInfo(currentRow); 339 340 /* TODO(chudy): Add command type before parameters. Rename v 341 * to something more informative. */ 342 if (currInfo) { 343 QString info; 344 info.append("<b>Parameters: </b><br/>"); 345 for (int i = 0; i < currInfo->count(); i++) { 346 info.append(QString((*currInfo)[i]->c_str())); 347 info.append("<br/>"); 348 } 349 fInspectorWidget.setText(info, SkInspectorWidget::kDetail_TabType); 350 } 351 352 fCurrentCommandBox.setText(QString::number(currentRow)); 353 354 fDrawCommandGeometryWidget.setDrawCommandIndex(currentRow); 355 356 fInspectorWidget.setDisabled(false); 357 fViewStateFrame.setDisabled(false); 358 } 359 } 360 361 void SkDebuggerGUI::selectCommand(int command) { 362 if (this->isPaused()) { 363 fListWidget.setCurrentRow(command); 364 } 365 } 366 367 void SkDebuggerGUI::toggleBreakpoint() { 368 QListWidgetItem* item = fListWidget.currentItem(); 369 if (item->checkState() == Qt::Unchecked) { 370 item->setCheckState(Qt::Checked); 371 item->setData(Qt::DecorationRole, 372 QPixmap(":/breakpoint_16x16.png")); 373 } else { 374 item->setCheckState(Qt::Unchecked); 375 item->setData(Qt::DecorationRole, 376 QPixmap(":/blank.png")); 377 } 378 } 379 380 void SkDebuggerGUI::toggleDirectory() { 381 fDirectoryWidget.setHidden(!fDirectoryWidget.isHidden()); 382 } 383 384 void SkDebuggerGUI::toggleFilter(QString string) { 385 for (int row = 0; row < fListWidget.count(); row++) { 386 QListWidgetItem *item = fListWidget.item(row); 387 item->setHidden(item->text() != string); 388 } 389 } 390 391 void SkDebuggerGUI::setupUi(QMainWindow *SkDebuggerGUI) { 392 QIcon windowIcon; 393 windowIcon.addFile(QString::fromUtf8(":/skia.png"), QSize(), 394 QIcon::Normal, QIcon::Off); 395 SkDebuggerGUI->setObjectName(QString::fromUtf8("SkDebuggerGUI")); 396 SkDebuggerGUI->resize(1200, 1000); 397 SkDebuggerGUI->setWindowIcon(windowIcon); 398 SkDebuggerGUI->setWindowTitle("Skia Debugger"); 399 400 fActionOpen.setShortcuts(QKeySequence::Open); 401 fActionOpen.setText("Open"); 402 403 QIcon breakpoint; 404 breakpoint.addFile(QString::fromUtf8(":/breakpoint.png"), 405 QSize(), QIcon::Normal, QIcon::Off); 406 fActionBreakpoint.setShortcut(QKeySequence(tr("Ctrl+B"))); 407 fActionBreakpoint.setIcon(breakpoint); 408 fActionBreakpoint.setText("Breakpoints"); 409 fActionBreakpoint.setCheckable(true); 410 411 QIcon cancel; 412 cancel.addFile(QString::fromUtf8(":/reload.png"), QSize(), 413 QIcon::Normal, QIcon::Off); 414 fActionCancel.setIcon(cancel); 415 fActionCancel.setText("Clear Filter"); 416 417 fActionClearBreakpoints.setShortcut(QKeySequence(tr("Alt+B"))); 418 fActionClearBreakpoints.setText("Clear Breakpoints"); 419 420 fActionClearDeletes.setShortcut(QKeySequence(tr("Alt+X"))); 421 fActionClearDeletes.setText("Clear Deletes"); 422 423 fActionClose.setShortcuts(QKeySequence::Quit); 424 fActionClose.setText("Exit"); 425 426 fActionCreateBreakpoint.setShortcut(QKeySequence(tr("B"))); 427 fActionCreateBreakpoint.setText("Set Breakpoint"); 428 429 fActionDelete.setShortcut(QKeySequence(tr("X"))); 430 fActionDelete.setText("Delete Command"); 431 432 fActionDirectory.setShortcut(QKeySequence(tr("Ctrl+D"))); 433 fActionDirectory.setText("Directory"); 434 435 QIcon inspector; 436 inspector.addFile(QString::fromUtf8(":/inspector.png"), 437 QSize(), QIcon::Normal, QIcon::Off); 438 fActionInspector.setShortcut(QKeySequence(tr("Ctrl+I"))); 439 fActionInspector.setIcon(inspector); 440 fActionInspector.setText("Inspector"); 441 442 QIcon settings; 443 settings.addFile(QString::fromUtf8(":/inspector.png"), 444 QSize(), QIcon::Normal, QIcon::Off); 445 fActionSettings.setShortcut(QKeySequence(tr("Ctrl+G"))); 446 fActionSettings.setIcon(settings); 447 fActionSettings.setText("Settings"); 448 449 QIcon play; 450 play.addFile(QString::fromUtf8(":/play.png"), QSize(), 451 QIcon::Normal, QIcon::Off); 452 fActionPlay.setShortcut(QKeySequence(tr("Ctrl+P"))); 453 fActionPlay.setIcon(play); 454 fActionPlay.setText("Play"); 455 456 QIcon pause; 457 pause.addFile(QString::fromUtf8(":/pause.png"), QSize(), 458 QIcon::Normal, QIcon::Off); 459 fActionPause.setShortcut(QKeySequence(tr("Space"))); 460 fActionPause.setCheckable(true); 461 fActionPause.setIcon(pause); 462 fActionPause.setText("Pause"); 463 464 QIcon rewind; 465 rewind.addFile(QString::fromUtf8(":/rewind.png"), QSize(), 466 QIcon::Normal, QIcon::Off); 467 fActionRewind.setShortcut(QKeySequence(tr("Ctrl+R"))); 468 fActionRewind.setIcon(rewind); 469 fActionRewind.setText("Rewind"); 470 471 fActionSave.setShortcut(QKeySequence::Save); 472 fActionSave.setText("Save"); 473 fActionSave.setDisabled(true); 474 fActionSaveAs.setShortcut(QKeySequence::SaveAs); 475 fActionSaveAs.setText("Save As"); 476 fActionSaveAs.setDisabled(true); 477 478 fActionShowDeletes.setShortcut(QKeySequence(tr("Ctrl+X"))); 479 fActionShowDeletes.setText("Deleted Commands"); 480 fActionShowDeletes.setCheckable(true); 481 482 QIcon stepBack; 483 stepBack.addFile(QString::fromUtf8(":/previous.png"), QSize(), 484 QIcon::Normal, QIcon::Off); 485 fActionStepBack.setShortcut(QKeySequence(tr("["))); 486 fActionStepBack.setIcon(stepBack); 487 fActionStepBack.setText("Step Back"); 488 489 QIcon stepForward; 490 stepForward.addFile(QString::fromUtf8(":/next.png"), 491 QSize(), QIcon::Normal, QIcon::Off); 492 fActionStepForward.setShortcut(QKeySequence(tr("]"))); 493 fActionStepForward.setIcon(stepForward); 494 fActionStepForward.setText("Step Forward"); 495 496 fActionZoomIn.setShortcut(QKeySequence(tr("Ctrl+="))); 497 fActionZoomIn.setText("Zoom In"); 498 fActionZoomOut.setShortcut(QKeySequence(tr("Ctrl+-"))); 499 fActionZoomOut.setText("Zoom Out"); 500 501 fListWidget.setItemDelegate(new SkListWidget(&fListWidget)); 502 fListWidget.setObjectName(QString::fromUtf8("listWidget")); 503 fListWidget.setMinimumWidth(250); 504 505 fFilter.addItem("--Filter By Available Commands--"); 506 507 fDirectoryWidget.setMinimumWidth(250); 508 fDirectoryWidget.setStyleSheet("QListWidget::Item {padding: 5px;}"); 509 510 fCanvasWidget.setSizePolicy(QSizePolicy::Expanding, 511 QSizePolicy::Expanding); 512 513 fDrawCommandGeometryWidget.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 514 515 fSettingsAndImageLayout.addWidget(&fSettingsWidget); 516 517 // View state group, part of inspector. 518 fViewStateFrame.setFrameStyle(QFrame::Panel); 519 fViewStateFrame.setLayout(&fViewStateFrameLayout); 520 fViewStateFrameLayout.addWidget(&fViewStateGroup); 521 fViewStateGroup.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); 522 fViewStateGroup.setTitle("View"); 523 fViewStateLayout.addRow("Zoom Level", &fZoomBox); 524 fZoomBox.setText("100%"); 525 fZoomBox.setMinimumSize(QSize(50,25)); 526 fZoomBox.setMaximumSize(QSize(50,25)); 527 fZoomBox.setAlignment(Qt::AlignRight); 528 fZoomBox.setReadOnly(true); 529 fViewStateLayout.addRow("Command HitBox", &fCommandHitBox); 530 fCommandHitBox.setText("0"); 531 fCommandHitBox.setMinimumSize(QSize(50,25)); 532 fCommandHitBox.setMaximumSize(QSize(50,25)); 533 fCommandHitBox.setAlignment(Qt::AlignRight); 534 fCommandHitBox.setReadOnly(true); 535 fViewStateLayout.addRow("Current Command", &fCurrentCommandBox); 536 fCurrentCommandBox.setText("0"); 537 fCurrentCommandBox.setMinimumSize(QSize(50,25)); 538 fCurrentCommandBox.setMaximumSize(QSize(50,25)); 539 fCurrentCommandBox.setAlignment(Qt::AlignRight); 540 fCurrentCommandBox.setReadOnly(true); 541 fViewStateGroup.setLayout(&fViewStateLayout); 542 fSettingsAndImageLayout.addWidget(&fViewStateFrame); 543 544 fDrawCommandGeometryWidget.setToolTip("Current Command Geometry"); 545 fSettingsAndImageLayout.addWidget(&fDrawCommandGeometryWidget); 546 547 fLeftColumnSplitter.addWidget(&fListWidget); 548 fLeftColumnSplitter.addWidget(&fDirectoryWidget); 549 fLeftColumnSplitter.setOrientation(Qt::Vertical); 550 551 fCanvasSettingsAndImageLayout.setSpacing(6); 552 fCanvasSettingsAndImageLayout.addWidget(&fCanvasWidget, 1); 553 fCanvasSettingsAndImageLayout.addLayout(&fSettingsAndImageLayout, 0); 554 555 fMainAndRightColumnLayout.setSpacing(6); 556 fMainAndRightColumnLayout.addLayout(&fCanvasSettingsAndImageLayout, 1); 557 fMainAndRightColumnLayout.addWidget(&fInspectorWidget, 0); 558 fMainAndRightColumnWidget.setLayout(&fMainAndRightColumnLayout); 559 560 fCentralSplitter.addWidget(&fLeftColumnSplitter); 561 fCentralSplitter.addWidget(&fMainAndRightColumnWidget); 562 fCentralSplitter.setStretchFactor(0, 0); 563 fCentralSplitter.setStretchFactor(1, 1); 564 565 SkDebuggerGUI->setCentralWidget(&fCentralSplitter); 566 SkDebuggerGUI->setStatusBar(&fStatusBar); 567 568 fToolBar.setIconSize(QSize(32, 32)); 569 fToolBar.setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 570 SkDebuggerGUI->addToolBar(Qt::TopToolBarArea, &fToolBar); 571 572 fSpacer.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 573 574 fToolBar.addAction(&fActionRewind); 575 fToolBar.addAction(&fActionStepBack); 576 fToolBar.addAction(&fActionPause); 577 fToolBar.addAction(&fActionStepForward); 578 fToolBar.addAction(&fActionPlay); 579 fToolBar.addSeparator(); 580 fToolBar.addAction(&fActionInspector); 581 fToolBar.addAction(&fActionSettings); 582 583 fToolBar.addSeparator(); 584 fToolBar.addWidget(&fSpacer); 585 fToolBar.addWidget(&fFilter); 586 fToolBar.addAction(&fActionCancel); 587 588 fFileName = ""; 589 setupDirectoryWidget(""); 590 591 // Menu Bar 592 fMenuFile.setTitle("File"); 593 fMenuFile.addAction(&fActionOpen); 594 fMenuFile.addAction(&fActionSave); 595 fMenuFile.addAction(&fActionSaveAs); 596 fMenuFile.addAction(&fActionClose); 597 598 fMenuEdit.setTitle("Edit"); 599 fMenuEdit.addAction(&fActionDelete); 600 fMenuEdit.addAction(&fActionClearDeletes); 601 fMenuEdit.addSeparator(); 602 fMenuEdit.addAction(&fActionCreateBreakpoint); 603 fMenuEdit.addAction(&fActionClearBreakpoints); 604 605 fMenuNavigate.setTitle("Navigate"); 606 fMenuNavigate.addAction(&fActionRewind); 607 fMenuNavigate.addAction(&fActionStepBack); 608 fMenuNavigate.addAction(&fActionStepForward); 609 fMenuNavigate.addAction(&fActionPlay); 610 fMenuNavigate.addAction(&fActionPause); 611 fMenuNavigate.addAction(&fActionGoToLine); 612 613 fMenuView.setTitle("View"); 614 fMenuView.addAction(&fActionBreakpoint); 615 fMenuView.addAction(&fActionShowDeletes); 616 fMenuView.addAction(&fActionZoomIn); 617 fMenuView.addAction(&fActionZoomOut); 618 619 fMenuWindows.setTitle("Window"); 620 fMenuWindows.addAction(&fActionInspector); 621 fMenuWindows.addAction(&fActionSettings); 622 fMenuWindows.addAction(&fActionDirectory); 623 624 fActionGoToLine.setText("Go to Line..."); 625 fActionGoToLine.setDisabled(true); 626 fMenuBar.addAction(fMenuFile.menuAction()); 627 fMenuBar.addAction(fMenuEdit.menuAction()); 628 fMenuBar.addAction(fMenuView.menuAction()); 629 fMenuBar.addAction(fMenuNavigate.menuAction()); 630 fMenuBar.addAction(fMenuWindows.menuAction()); 631 632 SkDebuggerGUI->setMenuBar(&fMenuBar); 633 QMetaObject::connectSlotsByName(SkDebuggerGUI); 634 } 635 636 void SkDebuggerGUI::setupDirectoryWidget(const QString& path) { 637 fPath = path; 638 populateDirectoryWidget(); 639 640 // clear the existing watched directory and setup a new directory to watch 641 if (!fDirectoryWatcher.directories().empty()) { 642 fDirectoryWatcher.removePaths(fDirectoryWatcher.directories()); 643 } 644 if (!path.isEmpty()) { 645 fDirectoryWatcher.addPath(fPath); 646 } 647 } 648 649 void SkDebuggerGUI::populateDirectoryWidget() { 650 QDir dir(fPath); 651 QRegExp r(".skp"); 652 const QStringList files = dir.entryList(); 653 654 // check if a file has been removed 655 for (int i = fDirectoryWidget.count() - 1; i >= 0; i--) { 656 QListWidgetItem* item = fDirectoryWidget.item(i); 657 if (!files.contains(item->text())) { 658 fDirectoryWidget.removeItemWidget(item); 659 delete item; 660 } 661 } 662 663 // add any new files 664 Q_FOREACH (QString f, files) { 665 if (f.contains(r) && fDirectoryWidget.findItems(f, Qt::MatchExactly).size() == 0) { 666 fDirectoryWidget.addItem(f); 667 } 668 } 669 } 670 671 void SkDebuggerGUI::loadPicture(const SkString& fileName) { 672 fFileName = fileName; 673 fLoading = true; 674 SkFILEStream stream(fileName.c_str()); 675 676 auto picture = SkPicture::MakeFromStream(&stream); 677 678 if (nullptr == picture) { 679 QMessageBox::critical(this, "Error loading file", "Couldn't read file, sorry."); 680 return; 681 } 682 683 fCanvasWidget.resetWidgetTransform(); 684 fDebugger.loadPicture(picture.get()); 685 686 fSkipCommands.setCount(fDebugger.getSize()); 687 for (int i = 0; i < fSkipCommands.count(); ++i) { 688 fSkipCommands[i] = false; 689 } 690 691 picture.reset(); 692 693 /* fDebugCanvas is reinitialized every load picture. Need it to retain value 694 * of the visibility filter. 695 * TODO(chudy): This should be deprecated since fDebugger is not 696 * recreated. 697 * */ 698 fDebugger.highlightCurrentCommand(fSettingsWidget.isVisibilityFilterEnabled()); 699 700 this->setupListWidget(); 701 this->setupComboBox(); 702 this->setupOverviewText(nullptr, 0.0, 1); 703 fInspectorWidget.setDisabled(false); 704 fViewStateFrame.setDisabled(false); 705 fSettingsWidget.setDisabled(false); 706 fMenuEdit.setDisabled(false); 707 fMenuNavigate.setDisabled(false); 708 fMenuView.setDisabled(false); 709 fActionSave.setDisabled(false); 710 fActionSaveAs.setDisabled(false); 711 fActionPause.setChecked(false); 712 fDrawCommandGeometryWidget.setDrawCommandIndex(-1); 713 714 fLoading = false; 715 actionPlay(); 716 } 717 718 void SkDebuggerGUI::setupListWidget() { 719 720 SkASSERT(!strcmp("Save", 721 SkDrawCommand::GetCommandString(SkDrawCommand::kSave_OpType))); 722 SkASSERT(!strcmp("SaveLayer", 723 SkDrawCommand::GetCommandString(SkDrawCommand::kSaveLayer_OpType))); 724 SkASSERT(!strcmp("Restore", 725 SkDrawCommand::GetCommandString(SkDrawCommand::kRestore_OpType))); 726 SkASSERT(!strcmp("BeginDrawPicture", 727 SkDrawCommand::GetCommandString(SkDrawCommand::kBeginDrawPicture_OpType))); 728 SkASSERT(!strcmp("EndDrawPicture", 729 SkDrawCommand::GetCommandString(SkDrawCommand::kEndDrawPicture_OpType))); 730 731 fListWidget.clear(); 732 int counter = 0; 733 int indent = 0; 734 for (int i = 0; i < fDebugger.getSize(); i++) { 735 QListWidgetItem *item = new QListWidgetItem(); 736 SkDrawCommand* command = fDebugger.getDrawCommandAt(i); 737 SkString commandString = command->toString(); 738 item->setData(Qt::DisplayRole, commandString.c_str()); 739 item->setData(Qt::UserRole + 1, counter++); 740 741 if (0 == strcmp("Restore", commandString.c_str()) || 742 0 == strcmp("EndDrawPicture", commandString.c_str())) { 743 indent -= 10; 744 } 745 746 item->setData(Qt::UserRole + 3, indent); 747 748 if (0 == strcmp("Save", commandString.c_str()) || 749 0 == strcmp("SaveLayer", commandString.c_str()) || 750 0 == strcmp("BeginDrawPicture", commandString.c_str())) { 751 indent += 10; 752 } 753 754 item->setData(Qt::UserRole + 4, -1); 755 756 fListWidget.addItem(item); 757 } 758 } 759 760 void SkDebuggerGUI::setupOverviewText(const SkTDArray<double>* typeTimes, 761 double totTime, 762 int numRuns) { 763 SkString overview; 764 fDebugger.getOverviewText(typeTimes, totTime, &overview, numRuns); 765 fInspectorWidget.setText(overview.c_str(), SkInspectorWidget::kOverview_TabType); 766 } 767 768 769 void SkDebuggerGUI::setupComboBox() { 770 fFilter.clear(); 771 fFilter.addItem("--Filter By Available Commands--"); 772 773 std::map<std::string, int> map; 774 for (int i = 0; i < fDebugger.getSize(); i++) { 775 map[fDebugger.getDrawCommandAt(i)->toString().c_str()]++; 776 } 777 778 for (std::map<std::string, int>::iterator it = map.begin(); it != map.end(); 779 ++it) { 780 fFilter.addItem((it->first).c_str()); 781 } 782 783 // NOTE(chudy): Makes first item unselectable. 784 QStandardItemModel* model = qobject_cast<QStandardItemModel*>( 785 fFilter.model()); 786 QModelIndex firstIndex = model->index(0, fFilter.modelColumn(), 787 fFilter.rootModelIndex()); 788 QStandardItem* firstItem = model->itemFromIndex(firstIndex); 789 firstItem->setSelectable(false); 790 } 791 792 void SkDebuggerGUI::updateImage() { 793 if (this->isPaused()) { 794 fCanvasWidget.drawTo(fPausedRow); 795 } else { 796 fCanvasWidget.drawTo(fListWidget.currentRow()); 797 } 798 } 799 800 void SkDebuggerGUI::updateHit(int newHit) { 801 fCommandHitBox.setText(QString::number(newHit)); 802 } 803 804