• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
SkDebuggerGUI(QWidget * parent)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  
actionBreakpoints()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  
showDeletes()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  
actionCancel()120  void SkDebuggerGUI::actionCancel() {
121      for (int row = 0; row < fListWidget.count(); row++) {
122          fListWidget.item(row)->setHidden(false);
123      }
124  }
125  
actionClearBreakpoints()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  
actionClearDeletes()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  
actionClose()145  void SkDebuggerGUI::actionClose() {
146      this->close();
147  }
148  
actionDelete()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
actionGLSettingsChanged()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  
actionInspector()182  void SkDebuggerGUI::actionInspector() {
183      bool newState = !fInspectorWidget.isHidden();
184  
185      fInspectorWidget.setHidden(newState);
186      fViewStateFrame.setHidden(newState);
187      fDrawCommandGeometryWidget.setHidden(newState);
188  }
189  
actionPlay()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  
actionRasterSettingsChanged()202  void SkDebuggerGUI::actionRasterSettingsChanged() {
203      fCanvasWidget.setWidgetVisibility(SkCanvasWidget::kRaster_8888_WidgetType,
204                                        !fSettingsWidget.isRasterEnabled());
205      this->updateImage();
206  }
207  
actionVisualizationsChanged()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  
actionTextureFilter()216  void SkDebuggerGUI::actionTextureFilter() {
217      SkFilterQuality quality;
218      bool enabled = fSettingsWidget.getFilterOverride(&quality);
219      fDebugger.setTexFilterOverride(enabled, quality);
220      fCanvasWidget.update();
221  }
222  
actionRewind()223  void SkDebuggerGUI::actionRewind() {
224      fListWidget.setCurrentRow(0);
225  }
226  
actionSave()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  
actionSaveAs()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  
actionScale(float scaleFactor)243  void SkDebuggerGUI::actionScale(float scaleFactor) {
244      fZoomBox.setText(QString::number(scaleFactor * 100, 'f', 0).append("%"));
245  }
246  
actionSettings()247  void SkDebuggerGUI::actionSettings() {
248      if (fSettingsWidget.isHidden()) {
249          fSettingsWidget.setHidden(false);
250      } else {
251          fSettingsWidget.setHidden(true);
252      }
253  }
254  
actionStepBack()255  void SkDebuggerGUI::actionStepBack() {
256      int currentRow = fListWidget.currentRow();
257      if (currentRow != 0) {
258          fListWidget.setCurrentRow(currentRow - 1);
259      }
260  }
261  
actionStepForward()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  
drawComplete()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  
saveToFile(const SkString & filename)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  
loadFile(QListWidgetItem * item)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  
openFile()307  void SkDebuggerGUI::openFile() {
308      QString temp = QFileDialog::getOpenFileName(this, tr("Open File"), "",
309              tr("Files (*.*)"));
310      openFile(temp);
311  }
312  
openFile(const QString & filename)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  
pauseDrawing(bool isPaused)321  void SkDebuggerGUI::pauseDrawing(bool isPaused) {
322      fPausedRow = fListWidget.currentRow();
323      this->updateDrawCommandInfo();
324  }
325  
updateDrawCommandInfo()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  
selectCommand(int command)362  void SkDebuggerGUI::selectCommand(int command) {
363      if (this->isPaused()) {
364          fListWidget.setCurrentRow(command);
365      }
366  }
367  
toggleBreakpoint()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  
toggleDirectory()381  void SkDebuggerGUI::toggleDirectory() {
382      fDirectoryWidget.setHidden(!fDirectoryWidget.isHidden());
383  }
384  
toggleFilter(QString string)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  
setupUi(QMainWindow * SkDebuggerGUI)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  
setupDirectoryWidget(const QString & path)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  
populateDirectoryWidget()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  
loadPicture(const SkString & fileName)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  
setupListWidget()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  
setupOverviewText(const SkTDArray<double> * typeTimes,double totTime,int numRuns)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  
setupComboBox()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  
updateImage()793  void SkDebuggerGUI::updateImage() {
794      if (this->isPaused()) {
795          fCanvasWidget.drawTo(fPausedRow);
796      } else {
797          fCanvasWidget.drawTo(fListWidget.currentRow());
798      }
799  }
800  
updateHit(int newHit)801  void SkDebuggerGUI::updateHit(int newHit) {
802      fCommandHitBox.setText(QString::number(newHit));
803  }
804  
805