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