File indexing completed on 2024-04-28 05:41:05
0001 /* 0002 Copyright (C) 2013-2014 Volker Krause <vkrause@kde.org> 0003 0004 This program is free software; you can redistribute it and/or modify it 0005 under the terms of the GNU Library General Public License as published by 0006 the Free Software Foundation; either version 2 of the License, or (at your 0007 option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, but WITHOUT 0010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 0012 License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program. If not, see <https://www.gnu.org/licenses/>. 0016 */ 0017 0018 #include "mainwindow.h" 0019 #include "ui_mainwindow.h" 0020 0021 #include <elf/elffileset.h> 0022 0023 #include <checks/structurepackingcheck.h> 0024 0025 #include <elfmodel/elfmodel.h> 0026 #include <navigator/codenavigator.h> 0027 0028 #include <QFileDialog> 0029 #include <QMessageBox> 0030 #include <QSettings> 0031 #include <QStatusBar> 0032 #include <QStandardItemModel> 0033 0034 #include <elf.h> 0035 0036 static void addView(QStandardItemModel *model, const QString& iconName, const QString& title) 0037 { 0038 auto icon = QIcon::fromTheme(iconName); 0039 if (icon.isNull()) 0040 icon = QIcon::fromTheme(QStringLiteral("dialog-information")); // fallback 0041 model->appendRow(new QStandardItem(icon, title)); 0042 } 0043 0044 MainWindow::MainWindow(QWidget* parent): QMainWindow(parent), ui(new Ui::MainWindow), m_elfModel(new ElfModel(this)) 0045 { 0046 ui->setupUi(this); 0047 0048 ui->elfStructureView->setModel(m_elfModel); 0049 ui->sizeTreeMapView->setModel(m_elfModel); 0050 0051 connect(ui->stackedWidget, &QStackedWidget::currentChanged, this, &MainWindow::currentViewChanged); 0052 0053 connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::fileOpen); 0054 connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::close); 0055 connect(ui->actionReopenPreviousFile, &QAction::triggered, this, &MainWindow::reloadFileOnStartup); 0056 0057 auto viewModel = new QStandardItemModel(this); 0058 addView(viewModel, QStringLiteral("document-preview"), QStringLiteral("ELF Structure")); 0059 addView(viewModel, QStringLiteral("table"), QStringLiteral("Size Tree Map")); 0060 addView(viewModel, QStringLiteral("view-list-tree"), QStringLiteral("Dependencies")); 0061 addView(viewModel, QStringLiteral("code-class"), QStringLiteral("Data Types")); 0062 addView(viewModel, QStringLiteral("chronometer"), QStringLiteral("Performance")); 0063 addView(viewModel, QStringLiteral("dialog-warning"), QStringLiteral("Issues")); 0064 ui->viewSelector->setModel(viewModel); 0065 connect(ui->viewSelector, &SidePane::currentIndexChanged, this, [this](int index){ 0066 ui->stackedWidget->setCurrentIndex(index); 0067 }); 0068 0069 ui->menuSettings->addAction(CodeNavigator::configMenu(this)); 0070 0071 restoreSettings(); 0072 currentViewChanged(); 0073 } 0074 0075 MainWindow::~MainWindow() 0076 { 0077 } 0078 0079 void MainWindow::closeEvent(QCloseEvent *event) 0080 { 0081 QSettings settings; 0082 settings.beginGroup(QStringLiteral("MainWindow")); 0083 settings.setValue(QStringLiteral("geometry"), saveGeometry()); 0084 settings.setValue(QStringLiteral("windowState"), saveState()); 0085 settings.setValue(QStringLiteral("currentView"), ui->stackedWidget->currentIndex()); 0086 settings.endGroup(); 0087 QMainWindow::closeEvent(event); 0088 } 0089 0090 void MainWindow::fileOpen() 0091 { 0092 const QFileInfo fi(m_currentFileName); 0093 0094 const QString fileName = QFileDialog::getOpenFileName(this, tr("Open ELF Object"), fi.path()); 0095 if (fileName.isEmpty()) 0096 return; 0097 0098 m_currentFileName = fileName; 0099 loadFile(fileName); 0100 } 0101 0102 void MainWindow::reloadFileOnStartup() 0103 { 0104 QSettings settings; 0105 settings.setValue(QStringLiteral("Settings/ReloadPreviousFile"), ui->actionReopenPreviousFile->isChecked()); 0106 } 0107 0108 void MainWindow::restoreSettings() 0109 { 0110 QSettings settings; 0111 ui->sizeTreeMapView->restoreSettings(); 0112 ui->actionReopenPreviousFile->setChecked(settings.value(QStringLiteral("Settings/ReloadPreviousFile"), false).toBool()); 0113 if (ui->actionReopenPreviousFile->isChecked()) { 0114 auto fileName = settings.value(QStringLiteral("Recent/PreviousFile")).toString(); 0115 const QFileInfo fi(fileName); 0116 if (!fi.isReadable() || !fi.isFile()) 0117 return; 0118 m_currentFileName = std::move(fileName); 0119 loadFile(m_currentFileName); 0120 } 0121 0122 settings.beginGroup(QStringLiteral("MainWindow")); 0123 restoreGeometry(settings.value(QStringLiteral("geometry")).toByteArray()); 0124 restoreState(settings.value(QStringLiteral("windowState")).toByteArray()); 0125 const auto currentViewIndex = settings.value(QStringLiteral("currentView"), 0).toInt(); 0126 const auto currentIdx = ui->viewSelector->model()->index(currentViewIndex, 0); 0127 ui->viewSelector->selectionModel()->select(currentIdx, QItemSelectionModel::ClearAndSelect); 0128 ui->viewSelector->selectionModel()->setCurrentIndex(currentIdx, QItemSelectionModel::ClearAndSelect); 0129 settings.endGroup(); 0130 } 0131 0132 void MainWindow::loadFile(const QString& fileName) 0133 { 0134 if (fileName.isEmpty() || windowFilePath() == fileName) 0135 return; 0136 setWindowFilePath(fileName); 0137 0138 m_fileSet.reset(new ElfFileSet(this)); 0139 m_fileSet->addFile(fileName); 0140 0141 if (m_fileSet->size() == 0) { 0142 QMessageBox::critical(this, tr("Failed to load ELF file"), tr("Could not load %1.").arg(fileName)); 0143 0144 m_fileSet.reset(); 0145 0146 statusBar()->showMessage(tr("Failed to load %1.").arg(fileName)); 0147 } else { 0148 m_fileSet->topologicalSort(); 0149 0150 QSettings settings; 0151 settings.setValue(QStringLiteral("Recent/PreviousFile"), fileName); 0152 0153 statusBar()->showMessage(tr("Loaded %1.").arg(fileName)); 0154 } 0155 0156 m_elfModel->setFileSet(m_fileSet.get()); 0157 ui->dependencyView->setFileSet(m_fileSet.get()); 0158 ui->loadTimeView->setFileSet(m_fileSet.get()); 0159 ui->typeView->setFileSet(m_fileSet.get()); 0160 ui->issuesView->setFileSet(m_fileSet.get()); 0161 } 0162 0163 void MainWindow::currentViewChanged() 0164 { 0165 ui->menuView->clear(); 0166 ui->menuView->addActions(ui->stackedWidget->currentWidget()->actions()); 0167 ui->menuView->setEnabled(!ui->menuView->isEmpty()); 0168 }