Home | History | Annotate | Download | only in mdbviz
      1 /*
      2  * Copyright 2017 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 <QtWidgets>
      9 
     10 #include "MainWindow.h"
     11 
     12 MainWindow::MainWindow() {
     13     this->createActions();
     14     this->createStatusBar();
     15     this->createDockWindows();
     16 
     17     this->setWindowTitle("MDB Viz");
     18 
     19     this->readSettings();
     20     this->setUnifiedTitleAndToolBarOnMac(true);
     21 }
     22 
     23 void MainWindow::openFile() {
     24     QString fileName = QFileDialog::getOpenFileName(this);
     25     if (!fileName.isEmpty()) {
     26         this->loadFile(fileName);
     27     }
     28 }
     29 
     30 void MainWindow::setupOpListWidget() {
     31     fOpListWidget->clear();
     32 
     33     QTreeWidgetItem* item = nullptr;
     34     SkTDArray<QTreeWidgetItem*> parents;
     35 
     36     for (int i = 0; i < fModel.numOps(); i++) {
     37         item = new QTreeWidgetItem();
     38 
     39         item->setText(0, QString::number(i));
     40         item->setData(0, Qt::UserRole, i);
     41         item->setText(1, fModel.getOpName(i));
     42 
     43         if (fModel.isHierarchyPop(i)) {
     44             parents.pop();
     45         }
     46 
     47         if (parents.isEmpty()) {
     48             fOpListWidget->addTopLevelItem(item);
     49         } else {
     50             parents.top()->addChild(item);
     51         }
     52 
     53         if (fModel.isHierarchyPush(i)) {
     54             *parents.push() = item;
     55         }
     56     }
     57 
     58     fOpListWidget->setCurrentItem(item);
     59     fOpListWidget->expandToDepth(100);
     60 }
     61 
     62 void MainWindow::presentCurrentRenderState() {
     63     fImage = QImage((uchar*)fModel.getPixels(), fModel.width(), fModel.height(),
     64                     QImage::Format_RGBA8888);
     65     fImageLabel->setPixmap(QPixmap::fromImage(fImage));
     66 }
     67 
     68 void MainWindow::loadFile(const QString &fileName) {
     69     QFile file(fileName);
     70     if (!file.open(QFile::ReadOnly | QFile::Text)) {
     71         QMessageBox::warning(this, tr("MDB Viz"),
     72                              tr("Cannot read file %1:\n%2.")
     73                              .arg(QDir::toNativeSeparators(fileName), file.errorString()));
     74         return;
     75     }
     76 
     77     QTextStream in(&file);
     78 #ifndef QT_NO_CURSOR
     79     QApplication::setOverrideCursor(Qt::WaitCursor);
     80 #endif
     81 
     82     std::string str = file.fileName().toLocal8Bit().constData();
     83 
     84     Model::ErrorCode err = fModel.load(str.c_str());
     85     if (Model::ErrorCode::kOK != err) {
     86         this->statusBar()->showMessage(Model::ErrorString(err));
     87         return;
     88     }
     89 
     90     this->setupOpListWidget();
     91     this->presentCurrentRenderState();
     92 
     93 #ifndef QT_NO_CURSOR
     94     QApplication::restoreOverrideCursor();
     95 #endif
     96 }
     97 
     98 
     99 void MainWindow::about() {
    100    QMessageBox::about(this, "About MDB Viz", "Visualize MDB");
    101 }
    102 
    103 void MainWindow::createActions() {
    104 
    105     // File menu
    106     QMenu* fileMenu = this->menuBar()->addMenu(tr("&File"));
    107     QToolBar* fileToolBar = this->addToolBar(tr("File"));
    108 
    109     const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(":/images/open.png"));
    110     QAction* openAct = new QAction(openIcon, tr("&Open..."), this);
    111     openAct->setShortcuts(QKeySequence::Open);
    112     openAct->setStatusTip(tr("Open an existing file"));
    113     connect(openAct, &QAction::triggered, this, &MainWindow::openFile);
    114     fileMenu->addAction(openAct);
    115     fileToolBar->addAction(openAct);
    116 
    117     fileMenu->addSeparator();
    118 
    119     const QIcon exitIcon = QIcon::fromTheme("application-exit");
    120     QAction *exitAct = fileMenu->addAction(exitIcon, tr("E&xit"), this, &QWidget::close);
    121     exitAct->setShortcuts(QKeySequence::Quit);
    122     exitAct->setStatusTip(tr("Exit the application"));
    123 
    124     // View menu
    125     fViewMenu = this->menuBar()->addMenu(tr("&View"));
    126 
    127     // Help menu
    128     this->menuBar()->addSeparator();
    129 
    130     QMenu* helpMenu = this->menuBar()->addMenu(tr("&Help"));
    131 
    132     QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &MainWindow::about);
    133     aboutAct->setStatusTip(tr("Show the application's About box"));
    134 }
    135 
    136 void MainWindow::onCurrentItemChanged(QTreeWidgetItem* cur, QTreeWidgetItem* /* prev */) {
    137     int currentRow = cur->data(0, Qt::UserRole).toInt();
    138     fModel.setCurOp(currentRow);
    139     this->presentCurrentRenderState();
    140 }
    141 
    142 void MainWindow::createStatusBar() {
    143     this->statusBar()->showMessage(tr("Ready"));
    144 }
    145 
    146 void MainWindow::createDockWindows() {
    147 
    148     // Op List Window
    149     {
    150         QDockWidget* opListDock = new QDockWidget("Ops", this);
    151         opListDock->setAllowedAreas(Qt::LeftDockWidgetArea);
    152 
    153         fOpListWidget = new QTreeWidget(opListDock);
    154 
    155         QTreeWidgetItem* headerItem = new QTreeWidgetItem;
    156         headerItem->setText(0, "Index");
    157         headerItem->setText(1, "Op Name");
    158         fOpListWidget->setHeaderItem(headerItem);
    159 
    160         fOpListWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
    161         fOpListWidget->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
    162 
    163         opListDock->setWidget(fOpListWidget);
    164         this->addDockWidget(Qt::LeftDockWidgetArea, opListDock);
    165 
    166         fViewMenu->addAction(opListDock->toggleViewAction());
    167 
    168         connect(fOpListWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
    169                 this, SLOT(onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
    170     }
    171 
    172     // Main canvas Window
    173     {
    174         QDockWidget* mainCanvasDock = new QDockWidget("Main Canvas", this);
    175         mainCanvasDock->setAllowedAreas(Qt::RightDockWidgetArea);
    176 
    177         fImageLabel = new QLabel(mainCanvasDock);
    178 
    179         fImage = QImage(1024, 1024, QImage::Format_RGBA8888);
    180         fImage.fill(0);
    181         fImageLabel->setPixmap(QPixmap::fromImage(fImage));
    182 
    183         mainCanvasDock->setWidget(fImageLabel);
    184         this->addDockWidget(Qt::RightDockWidgetArea, mainCanvasDock);
    185 
    186         fViewMenu->addAction(mainCanvasDock->toggleViewAction());
    187     }
    188 }
    189 
    190 void MainWindow::readSettings() {
    191     QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
    192     const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
    193     if (geometry.isEmpty()) {
    194         const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
    195         resize(availableGeometry.width() / 3, availableGeometry.height() / 2);
    196         move((availableGeometry.width() - width()) / 2,
    197              (availableGeometry.height() - height()) / 2);
    198     } else {
    199         this->restoreGeometry(geometry);
    200     }
    201 }
    202 
    203 void MainWindow::writeSettings() {
    204     QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
    205     settings.setValue("geometry", this->saveGeometry());
    206 }
    207