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