• Home
  • 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