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