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