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 SkAutoTUnref<SkPicture> copy(fDebugger.copyPicture()); 283 284 SkAutoTUnref<SkPixelSerializer> serializer( 285 SkImageEncoder::CreatePixelSerializer()); 286 copy->serialize(&file, serializer); 287 } 288 289 void SkDebuggerGUI::loadFile(QListWidgetItem *item) { 290 if (item == nullptr) { 291 return; 292 } 293 294 SkString fileName(fPath.toAscii().data()); 295 // don't add a '/' to files in the local directory 296 if (fileName.size() > 0) { 297 fileName.append("/"); 298 } 299 fileName.append(item->text().toAscii().data()); 300 301 if (!fileName.equals(fFileName)) { 302 fFileName = fileName; 303 loadPicture(fFileName); 304 } 305 } 306 307 void SkDebuggerGUI::openFile() { 308 QString temp = QFileDialog::getOpenFileName(this, tr("Open File"), "", 309 tr("Files (*.*)")); 310 openFile(temp); 311 } 312 313 void SkDebuggerGUI::openFile(const QString &filename) { 314 if (!filename.isEmpty()) { 315 QFileInfo pathInfo(filename); 316 loadPicture(SkString(filename.toAscii().data())); 317 setupDirectoryWidget(pathInfo.path()); 318 } 319 } 320 321 void SkDebuggerGUI::pauseDrawing(bool isPaused) { 322 fPausedRow = fListWidget.currentRow(); 323 this->updateDrawCommandInfo(); 324 } 325 326 void SkDebuggerGUI::updateDrawCommandInfo() { 327 int currentRow = -1; 328 if (!fLoading) { 329 currentRow = fListWidget.currentRow(); 330 } 331 if (currentRow == -1) { 332 fInspectorWidget.setText("", SkInspectorWidget::kDetail_TabType); 333 fInspectorWidget.setText("", SkInspectorWidget::kClipStack_TabType); 334 fCurrentCommandBox.setText(""); 335 fDrawCommandGeometryWidget.setDrawCommandIndex(-1); 336 } else { 337 this->updateImage(); 338 339 const SkTDArray<SkString*> *currInfo = fDebugger.getCommandInfo(currentRow); 340 341 /* TODO(chudy): Add command type before parameters. Rename v 342 * to something more informative. */ 343 if (currInfo) { 344 QString info; 345 info.append("<b>Parameters: </b><br/>"); 346 for (int i = 0; i < currInfo->count(); i++) { 347 info.append(QString((*currInfo)[i]->c_str())); 348 info.append("<br/>"); 349 } 350 fInspectorWidget.setText(info, SkInspectorWidget::kDetail_TabType); 351 } 352 353 fCurrentCommandBox.setText(QString::number(currentRow)); 354 355 fDrawCommandGeometryWidget.setDrawCommandIndex(currentRow); 356 357 fInspectorWidget.setDisabled(false); 358 fViewStateFrame.setDisabled(false); 359 } 360 } 361 362 void SkDebuggerGUI::selectCommand(int command) { 363 if (this->isPaused()) { 364 fListWidget.setCurrentRow(command); 365 } 366 } 367 368 void SkDebuggerGUI::toggleBreakpoint() { 369 QListWidgetItem* item = fListWidget.currentItem(); 370 if (item->checkState() == Qt::Unchecked) { 371 item->setCheckState(Qt::Checked); 372 item->setData(Qt::DecorationRole, 373 QPixmap(":/breakpoint_16x16.png")); 374 } else { 375 item->setCheckState(Qt::Unchecked); 376 item->setData(Qt::DecorationRole, 377 QPixmap(":/blank.png")); 378 } 379 } 380 381 void SkDebuggerGUI::toggleDirectory() { 382 fDirectoryWidget.setHidden(!fDirectoryWidget.isHidden()); 383 } 384 385 void SkDebuggerGUI::toggleFilter(QString string) { 386 for (int row = 0; row < fListWidget.count(); row++) { 387 QListWidgetItem *item = fListWidget.item(row); 388 item->setHidden(item->text() != string); 389 } 390 } 391 392 void SkDebuggerGUI::setupUi(QMainWindow *SkDebuggerGUI) { 393 QIcon windowIcon; 394 windowIcon.addFile(QString::fromUtf8(":/skia.png"), QSize(), 395 QIcon::Normal, QIcon::Off); 396 SkDebuggerGUI->setObjectName(QString::fromUtf8("SkDebuggerGUI")); 397 SkDebuggerGUI->resize(1200, 1000); 398 SkDebuggerGUI->setWindowIcon(windowIcon); 399 SkDebuggerGUI->setWindowTitle("Skia Debugger"); 400 401 fActionOpen.setShortcuts(QKeySequence::Open); 402 fActionOpen.setText("Open"); 403 404 QIcon breakpoint; 405 breakpoint.addFile(QString::fromUtf8(":/breakpoint.png"), 406 QSize(), QIcon::Normal, QIcon::Off); 407 fActionBreakpoint.setShortcut(QKeySequence(tr("Ctrl+B"))); 408 fActionBreakpoint.setIcon(breakpoint); 409 fActionBreakpoint.setText("Breakpoints"); 410 fActionBreakpoint.setCheckable(true); 411 412 QIcon cancel; 413 cancel.addFile(QString::fromUtf8(":/reload.png"), QSize(), 414 QIcon::Normal, QIcon::Off); 415 fActionCancel.setIcon(cancel); 416 fActionCancel.setText("Clear Filter"); 417 418 fActionClearBreakpoints.setShortcut(QKeySequence(tr("Alt+B"))); 419 fActionClearBreakpoints.setText("Clear Breakpoints"); 420 421 fActionClearDeletes.setShortcut(QKeySequence(tr("Alt+X"))); 422 fActionClearDeletes.setText("Clear Deletes"); 423 424 fActionClose.setShortcuts(QKeySequence::Quit); 425 fActionClose.setText("Exit"); 426 427 fActionCreateBreakpoint.setShortcut(QKeySequence(tr("B"))); 428 fActionCreateBreakpoint.setText("Set Breakpoint"); 429 430 fActionDelete.setShortcut(QKeySequence(tr("X"))); 431 fActionDelete.setText("Delete Command"); 432 433 fActionDirectory.setShortcut(QKeySequence(tr("Ctrl+D"))); 434 fActionDirectory.setText("Directory"); 435 436 QIcon inspector; 437 inspector.addFile(QString::fromUtf8(":/inspector.png"), 438 QSize(), QIcon::Normal, QIcon::Off); 439 fActionInspector.setShortcut(QKeySequence(tr("Ctrl+I"))); 440 fActionInspector.setIcon(inspector); 441 fActionInspector.setText("Inspector"); 442 443 QIcon settings; 444 settings.addFile(QString::fromUtf8(":/inspector.png"), 445 QSize(), QIcon::Normal, QIcon::Off); 446 fActionSettings.setShortcut(QKeySequence(tr("Ctrl+G"))); 447 fActionSettings.setIcon(settings); 448 fActionSettings.setText("Settings"); 449 450 QIcon play; 451 play.addFile(QString::fromUtf8(":/play.png"), QSize(), 452 QIcon::Normal, QIcon::Off); 453 fActionPlay.setShortcut(QKeySequence(tr("Ctrl+P"))); 454 fActionPlay.setIcon(play); 455 fActionPlay.setText("Play"); 456 457 QIcon pause; 458 pause.addFile(QString::fromUtf8(":/pause.png"), QSize(), 459 QIcon::Normal, QIcon::Off); 460 fActionPause.setShortcut(QKeySequence(tr("Space"))); 461 fActionPause.setCheckable(true); 462 fActionPause.setIcon(pause); 463 fActionPause.setText("Pause"); 464 465 QIcon rewind; 466 rewind.addFile(QString::fromUtf8(":/rewind.png"), QSize(), 467 QIcon::Normal, QIcon::Off); 468 fActionRewind.setShortcut(QKeySequence(tr("Ctrl+R"))); 469 fActionRewind.setIcon(rewind); 470 fActionRewind.setText("Rewind"); 471 472 fActionSave.setShortcut(QKeySequence::Save); 473 fActionSave.setText("Save"); 474 fActionSave.setDisabled(true); 475 fActionSaveAs.setShortcut(QKeySequence::SaveAs); 476 fActionSaveAs.setText("Save As"); 477 fActionSaveAs.setDisabled(true); 478 479 fActionShowDeletes.setShortcut(QKeySequence(tr("Ctrl+X"))); 480 fActionShowDeletes.setText("Deleted Commands"); 481 fActionShowDeletes.setCheckable(true); 482 483 QIcon stepBack; 484 stepBack.addFile(QString::fromUtf8(":/previous.png"), QSize(), 485 QIcon::Normal, QIcon::Off); 486 fActionStepBack.setShortcut(QKeySequence(tr("["))); 487 fActionStepBack.setIcon(stepBack); 488 fActionStepBack.setText("Step Back"); 489 490 QIcon stepForward; 491 stepForward.addFile(QString::fromUtf8(":/next.png"), 492 QSize(), QIcon::Normal, QIcon::Off); 493 fActionStepForward.setShortcut(QKeySequence(tr("]"))); 494 fActionStepForward.setIcon(stepForward); 495 fActionStepForward.setText("Step Forward"); 496 497 fActionZoomIn.setShortcut(QKeySequence(tr("Ctrl+="))); 498 fActionZoomIn.setText("Zoom In"); 499 fActionZoomOut.setShortcut(QKeySequence(tr("Ctrl+-"))); 500 fActionZoomOut.setText("Zoom Out"); 501 502 fListWidget.setItemDelegate(new SkListWidget(&fListWidget)); 503 fListWidget.setObjectName(QString::fromUtf8("listWidget")); 504 fListWidget.setMinimumWidth(250); 505 506 fFilter.addItem("--Filter By Available Commands--"); 507 508 fDirectoryWidget.setMinimumWidth(250); 509 fDirectoryWidget.setStyleSheet("QListWidget::Item {padding: 5px;}"); 510 511 fCanvasWidget.setSizePolicy(QSizePolicy::Expanding, 512 QSizePolicy::Expanding); 513 514 fDrawCommandGeometryWidget.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 515 516 fSettingsAndImageLayout.addWidget(&fSettingsWidget); 517 518 // View state group, part of inspector. 519 fViewStateFrame.setFrameStyle(QFrame::Panel); 520 fViewStateFrame.setLayout(&fViewStateFrameLayout); 521 fViewStateFrameLayout.addWidget(&fViewStateGroup); 522 fViewStateGroup.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); 523 fViewStateGroup.setTitle("View"); 524 fViewStateLayout.addRow("Zoom Level", &fZoomBox); 525 fZoomBox.setText("100%"); 526 fZoomBox.setMinimumSize(QSize(50,25)); 527 fZoomBox.setMaximumSize(QSize(50,25)); 528 fZoomBox.setAlignment(Qt::AlignRight); 529 fZoomBox.setReadOnly(true); 530 fViewStateLayout.addRow("Command HitBox", &fCommandHitBox); 531 fCommandHitBox.setText("0"); 532 fCommandHitBox.setMinimumSize(QSize(50,25)); 533 fCommandHitBox.setMaximumSize(QSize(50,25)); 534 fCommandHitBox.setAlignment(Qt::AlignRight); 535 fCommandHitBox.setReadOnly(true); 536 fViewStateLayout.addRow("Current Command", &fCurrentCommandBox); 537 fCurrentCommandBox.setText("0"); 538 fCurrentCommandBox.setMinimumSize(QSize(50,25)); 539 fCurrentCommandBox.setMaximumSize(QSize(50,25)); 540 fCurrentCommandBox.setAlignment(Qt::AlignRight); 541 fCurrentCommandBox.setReadOnly(true); 542 fViewStateGroup.setLayout(&fViewStateLayout); 543 fSettingsAndImageLayout.addWidget(&fViewStateFrame); 544 545 fDrawCommandGeometryWidget.setToolTip("Current Command Geometry"); 546 fSettingsAndImageLayout.addWidget(&fDrawCommandGeometryWidget); 547 548 fLeftColumnSplitter.addWidget(&fListWidget); 549 fLeftColumnSplitter.addWidget(&fDirectoryWidget); 550 fLeftColumnSplitter.setOrientation(Qt::Vertical); 551 552 fCanvasSettingsAndImageLayout.setSpacing(6); 553 fCanvasSettingsAndImageLayout.addWidget(&fCanvasWidget, 1); 554 fCanvasSettingsAndImageLayout.addLayout(&fSettingsAndImageLayout, 0); 555 556 fMainAndRightColumnLayout.setSpacing(6); 557 fMainAndRightColumnLayout.addLayout(&fCanvasSettingsAndImageLayout, 1); 558 fMainAndRightColumnLayout.addWidget(&fInspectorWidget, 0); 559 fMainAndRightColumnWidget.setLayout(&fMainAndRightColumnLayout); 560 561 fCentralSplitter.addWidget(&fLeftColumnSplitter); 562 fCentralSplitter.addWidget(&fMainAndRightColumnWidget); 563 fCentralSplitter.setStretchFactor(0, 0); 564 fCentralSplitter.setStretchFactor(1, 1); 565 566 SkDebuggerGUI->setCentralWidget(&fCentralSplitter); 567 SkDebuggerGUI->setStatusBar(&fStatusBar); 568 569 fToolBar.setIconSize(QSize(32, 32)); 570 fToolBar.setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 571 SkDebuggerGUI->addToolBar(Qt::TopToolBarArea, &fToolBar); 572 573 fSpacer.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 574 575 fToolBar.addAction(&fActionRewind); 576 fToolBar.addAction(&fActionStepBack); 577 fToolBar.addAction(&fActionPause); 578 fToolBar.addAction(&fActionStepForward); 579 fToolBar.addAction(&fActionPlay); 580 fToolBar.addSeparator(); 581 fToolBar.addAction(&fActionInspector); 582 fToolBar.addAction(&fActionSettings); 583 584 fToolBar.addSeparator(); 585 fToolBar.addWidget(&fSpacer); 586 fToolBar.addWidget(&fFilter); 587 fToolBar.addAction(&fActionCancel); 588 589 fFileName = ""; 590 setupDirectoryWidget(""); 591 592 // Menu Bar 593 fMenuFile.setTitle("File"); 594 fMenuFile.addAction(&fActionOpen); 595 fMenuFile.addAction(&fActionSave); 596 fMenuFile.addAction(&fActionSaveAs); 597 fMenuFile.addAction(&fActionClose); 598 599 fMenuEdit.setTitle("Edit"); 600 fMenuEdit.addAction(&fActionDelete); 601 fMenuEdit.addAction(&fActionClearDeletes); 602 fMenuEdit.addSeparator(); 603 fMenuEdit.addAction(&fActionCreateBreakpoint); 604 fMenuEdit.addAction(&fActionClearBreakpoints); 605 606 fMenuNavigate.setTitle("Navigate"); 607 fMenuNavigate.addAction(&fActionRewind); 608 fMenuNavigate.addAction(&fActionStepBack); 609 fMenuNavigate.addAction(&fActionStepForward); 610 fMenuNavigate.addAction(&fActionPlay); 611 fMenuNavigate.addAction(&fActionPause); 612 fMenuNavigate.addAction(&fActionGoToLine); 613 614 fMenuView.setTitle("View"); 615 fMenuView.addAction(&fActionBreakpoint); 616 fMenuView.addAction(&fActionShowDeletes); 617 fMenuView.addAction(&fActionZoomIn); 618 fMenuView.addAction(&fActionZoomOut); 619 620 fMenuWindows.setTitle("Window"); 621 fMenuWindows.addAction(&fActionInspector); 622 fMenuWindows.addAction(&fActionSettings); 623 fMenuWindows.addAction(&fActionDirectory); 624 625 fActionGoToLine.setText("Go to Line..."); 626 fActionGoToLine.setDisabled(true); 627 fMenuBar.addAction(fMenuFile.menuAction()); 628 fMenuBar.addAction(fMenuEdit.menuAction()); 629 fMenuBar.addAction(fMenuView.menuAction()); 630 fMenuBar.addAction(fMenuNavigate.menuAction()); 631 fMenuBar.addAction(fMenuWindows.menuAction()); 632 633 SkDebuggerGUI->setMenuBar(&fMenuBar); 634 QMetaObject::connectSlotsByName(SkDebuggerGUI); 635 } 636 637 void SkDebuggerGUI::setupDirectoryWidget(const QString& path) { 638 fPath = path; 639 populateDirectoryWidget(); 640 641 // clear the existing watched directory and setup a new directory to watch 642 if (!fDirectoryWatcher.directories().empty()) { 643 fDirectoryWatcher.removePaths(fDirectoryWatcher.directories()); 644 } 645 if (!path.isEmpty()) { 646 fDirectoryWatcher.addPath(fPath); 647 } 648 } 649 650 void SkDebuggerGUI::populateDirectoryWidget() { 651 QDir dir(fPath); 652 QRegExp r(".skp"); 653 const QStringList files = dir.entryList(); 654 655 // check if a file has been removed 656 for (int i = fDirectoryWidget.count() - 1; i >= 0; i--) { 657 QListWidgetItem* item = fDirectoryWidget.item(i); 658 if (!files.contains(item->text())) { 659 fDirectoryWidget.removeItemWidget(item); 660 delete item; 661 } 662 } 663 664 // add any new files 665 foreach (QString f, files) { 666 if (f.contains(r) && fDirectoryWidget.findItems(f, Qt::MatchExactly).size() == 0) { 667 fDirectoryWidget.addItem(f); 668 } 669 } 670 } 671 672 void SkDebuggerGUI::loadPicture(const SkString& fileName) { 673 fFileName = fileName; 674 fLoading = true; 675 SkAutoTDelete<SkStream> stream(new SkFILEStream(fileName.c_str())); 676 677 SkPicture* picture = SkPicture::CreateFromStream(stream); 678 679 if (nullptr == picture) { 680 QMessageBox::critical(this, "Error loading file", "Couldn't read file, sorry."); 681 return; 682 } 683 684 fCanvasWidget.resetWidgetTransform(); 685 fDebugger.loadPicture(picture); 686 687 fSkipCommands.setCount(fDebugger.getSize()); 688 for (int i = 0; i < fSkipCommands.count(); ++i) { 689 fSkipCommands[i] = false; 690 } 691 692 SkSafeUnref(picture); 693 694 /* fDebugCanvas is reinitialized every load picture. Need it to retain value 695 * of the visibility filter. 696 * TODO(chudy): This should be deprecated since fDebugger is not 697 * recreated. 698 * */ 699 fDebugger.highlightCurrentCommand(fSettingsWidget.isVisibilityFilterEnabled()); 700 701 this->setupListWidget(); 702 this->setupComboBox(); 703 this->setupOverviewText(nullptr, 0.0, 1); 704 fInspectorWidget.setDisabled(false); 705 fViewStateFrame.setDisabled(false); 706 fSettingsWidget.setDisabled(false); 707 fMenuEdit.setDisabled(false); 708 fMenuNavigate.setDisabled(false); 709 fMenuView.setDisabled(false); 710 fActionSave.setDisabled(false); 711 fActionSaveAs.setDisabled(false); 712 fActionPause.setChecked(false); 713 fDrawCommandGeometryWidget.setDrawCommandIndex(-1); 714 715 fLoading = false; 716 actionPlay(); 717 } 718 719 void SkDebuggerGUI::setupListWidget() { 720 721 SkASSERT(!strcmp("Save", 722 SkDrawCommand::GetCommandString(SkDrawCommand::kSave_OpType))); 723 SkASSERT(!strcmp("SaveLayer", 724 SkDrawCommand::GetCommandString(SkDrawCommand::kSaveLayer_OpType))); 725 SkASSERT(!strcmp("Restore", 726 SkDrawCommand::GetCommandString(SkDrawCommand::kRestore_OpType))); 727 SkASSERT(!strcmp("BeginDrawPicture", 728 SkDrawCommand::GetCommandString(SkDrawCommand::kBeginDrawPicture_OpType))); 729 SkASSERT(!strcmp("EndDrawPicture", 730 SkDrawCommand::GetCommandString(SkDrawCommand::kEndDrawPicture_OpType))); 731 732 fListWidget.clear(); 733 int counter = 0; 734 int indent = 0; 735 for (int i = 0; i < fDebugger.getSize(); i++) { 736 QListWidgetItem *item = new QListWidgetItem(); 737 SkDrawCommand* command = fDebugger.getDrawCommandAt(i); 738 SkString commandString = command->toString(); 739 item->setData(Qt::DisplayRole, commandString.c_str()); 740 item->setData(Qt::UserRole + 1, counter++); 741 742 if (0 == strcmp("Restore", commandString.c_str()) || 743 0 == strcmp("EndDrawPicture", commandString.c_str())) { 744 indent -= 10; 745 } 746 747 item->setData(Qt::UserRole + 3, indent); 748 749 if (0 == strcmp("Save", commandString.c_str()) || 750 0 == strcmp("SaveLayer", commandString.c_str()) || 751 0 == strcmp("BeginDrawPicture", commandString.c_str())) { 752 indent += 10; 753 } 754 755 item->setData(Qt::UserRole + 4, -1); 756 757 fListWidget.addItem(item); 758 } 759 } 760 761 void SkDebuggerGUI::setupOverviewText(const SkTDArray<double>* typeTimes, 762 double totTime, 763 int numRuns) { 764 SkString overview; 765 fDebugger.getOverviewText(typeTimes, totTime, &overview, numRuns); 766 fInspectorWidget.setText(overview.c_str(), SkInspectorWidget::kOverview_TabType); 767 } 768 769 770 void SkDebuggerGUI::setupComboBox() { 771 fFilter.clear(); 772 fFilter.addItem("--Filter By Available Commands--"); 773 774 std::map<std::string, int> map; 775 for (int i = 0; i < fDebugger.getSize(); i++) { 776 map[fDebugger.getDrawCommandAt(i)->toString().c_str()]++; 777 } 778 779 for (std::map<std::string, int>::iterator it = map.begin(); it != map.end(); 780 ++it) { 781 fFilter.addItem((it->first).c_str()); 782 } 783 784 // NOTE(chudy): Makes first item unselectable. 785 QStandardItemModel* model = qobject_cast<QStandardItemModel*>( 786 fFilter.model()); 787 QModelIndex firstIndex = model->index(0, fFilter.modelColumn(), 788 fFilter.rootModelIndex()); 789 QStandardItem* firstItem = model->itemFromIndex(firstIndex); 790 firstItem->setSelectable(false); 791 } 792 793 void SkDebuggerGUI::updateImage() { 794 if (this->isPaused()) { 795 fCanvasWidget.drawTo(fPausedRow); 796 } else { 797 fCanvasWidget.drawTo(fListWidget.currentRow()); 798 } 799 } 800 801 void SkDebuggerGUI::updateHit(int newHit) { 802 fCommandHitBox.setText(QString::number(newHit)); 803 } 804 805