diff --git a/src/ui/elfmodel/sectionproxymodel.cpp b/src/ui/elfmodel/sectionproxymodel.cpp index 7cdbabd..0dc97a4 100644 --- a/src/ui/elfmodel/sectionproxymodel.cpp +++ b/src/ui/elfmodel/sectionproxymodel.cpp @@ -1,35 +1,50 @@ /* Copyright (C) 2015 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "sectionproxymodel.h" #include "elfmodel.h" -SectionProxyModel::SectionProxyModel(QObject* parent): KRecursiveFilterProxyModel(parent) +SectionProxyModel::SectionProxyModel(QObject* parent): QSortFilterProxyModel(parent) { } SectionProxyModel::~SectionProxyModel() = default; bool SectionProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const { const auto sourceIndex = sourceModel()->index(source_row, 0, source_parent); const auto fileData = sourceModel()->data(sourceIndex, ElfModel::FileRole); const auto secData = sourceModel()->data(sourceIndex, ElfModel::SectionRole); - if (fileData.isNull() && secData.isNull()) + + if (fileData.isNull() && secData.isNull()) { return false; - return KRecursiveFilterProxyModel::filterAcceptsRow(source_row, source_parent); + } else if (QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent)) { + return true; + } + // implement our own recursive filtering, + // code taken from KRecursiveFilterProxyModel::filterAcceptsRow() + bool accepted = false; + + const int numChildren = sourceModel()->rowCount(sourceIndex); + for (int row = 0, rows = numChildren; row < rows; ++row) { + if (filterAcceptsRow(row, sourceIndex)) { + accepted = true; + break; + } + } + return accepted; } diff --git a/src/ui/elfmodel/sectionproxymodel.h b/src/ui/elfmodel/sectionproxymodel.h index 5058b40..fe6ccc6 100644 --- a/src/ui/elfmodel/sectionproxymodel.h +++ b/src/ui/elfmodel/sectionproxymodel.h @@ -1,34 +1,34 @@ /* Copyright (C) 2015 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef SECTIONPROXYMODEL_H #define SECTIONPROXYMODEL_H -#include +#include /** Restrict the structure model to just files and sections. */ -class SectionProxyModel : public KRecursiveFilterProxyModel +class SectionProxyModel : public QSortFilterProxyModel { Q_OBJECT public: explicit SectionProxyModel(QObject* parent = nullptr); ~SectionProxyModel(); bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const final override; }; #endif // SECTIONPROXYMODEL_H diff --git a/src/ui/views/elfstructureview.cpp b/src/ui/views/elfstructureview.cpp index 9df1d46..e3108b7 100644 --- a/src/ui/views/elfstructureview.cpp +++ b/src/ui/views/elfstructureview.cpp @@ -1,133 +1,134 @@ /* Copyright (C) 2015 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "elfstructureview.h" #include "ui_elfstructureview.h" #include #include -#include +#include #include ElfStructureView::ElfStructureView(QWidget* parent): QWidget(parent), ui(new Ui::ElfStructureView), - m_proxy(new KRecursiveFilterProxyModel(this)) + m_proxy(new QSortFilterProxyModel(this)) { ui->setupUi(this); ui->elfStructureView->setModel(m_proxy); + m_proxy->setRecursiveFilteringEnabled(true); ui->elfStructureView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); connect(ui->elfStructureView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ElfStructureView::selectionChanged); connect(ui->elfStructureSearchLine, &QLineEdit::textChanged, this, [this](const QString &text) { m_proxy->setFilterFixedString(text); }); connect(ui->elfDetailView, &QTextBrowser::anchorClicked, this, &ElfStructureView::anchorClicked); ui->actionBack->setShortcut(QKeySequence::Back); ui->actionForward->setShortcut(QKeySequence::Forward); connect(ui->actionBack, &QAction::triggered, this, [this]() { --m_historyIndex; m_historyLock = true; selectUrl(m_history.at(m_historyIndex)); m_historyLock = false; updateActionState(); }); connect(ui->actionForward, &QAction::triggered, this, [this]() { ++m_historyIndex; m_historyLock = true; selectUrl(m_history.at(m_historyIndex)); m_historyLock = false; updateActionState(); }); addActions({ ui->actionBack, ui->actionForward }); updateActionState(); installEventFilter(this); } ElfStructureView::~ElfStructureView() = default; void ElfStructureView::setModel(ElfModel* model) { m_elfModel = model; m_proxy->setSourceModel(model); } void ElfStructureView::selectionChanged(const QItemSelection &selection) { if (selection.isEmpty()) { ui->elfDetailView->clear(); return; } const QModelIndex index = selection.first().topLeft(); ui->elfDetailView->setHtml(index.data(ElfModel::DetailRole).toString()); if (m_historyLock) return; const auto url = index.data(ElfModel::NodeUrl).toUrl(); if (url.isValid() && !url.isEmpty()) { m_history.resize(m_historyIndex + 2); m_history[++m_historyIndex] = url; updateActionState(); } } void ElfStructureView::anchorClicked(const QUrl& url) { if (url.scheme() == QLatin1String("code")) CodeNavigator::goTo(url); else if (url.scheme() == QLatin1String("elfmodel")) selectUrl(url); } void ElfStructureView::updateActionState() { ui->actionBack->setEnabled(m_historyIndex > 0); ui->actionForward->setEnabled(m_historyIndex + 1 < m_history.size()); } void ElfStructureView::selectUrl(const QUrl& url) { auto idx = m_elfModel->indexForUrl(url); idx = m_proxy->mapFromSource(idx); ui->elfStructureView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); ui->elfStructureView->selectionModel()->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); ui->elfStructureView->scrollTo(idx); } bool ElfStructureView::eventFilter(QObject *receiver, QEvent *event) { if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) { auto mouseEv = static_cast(event); if (mouseEv->button() == Qt::BackButton) { if (ui->actionBack->isEnabled()) ui->actionBack->trigger(); return true; } else if (mouseEv->button() == Qt::ForwardButton) { if (ui->actionForward->isEnabled()) ui->actionForward->trigger(); return true; } } return QObject::eventFilter(receiver, event); } diff --git a/src/ui/views/typeview.cpp b/src/ui/views/typeview.cpp index f9aaf5a..0edbf58 100644 --- a/src/ui/views/typeview.cpp +++ b/src/ui/views/typeview.cpp @@ -1,87 +1,87 @@ /* Copyright (C) 2015 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "typeview.h" #include "ui_typeview.h" #include #include -#include - #include #include +#include TypeView::TypeView(QWidget* parent): QWidget(parent), ui(new Ui::TypeView), m_model(new TypeModel(this)) { ui->setupUi(this); - auto proxy = new KRecursiveFilterProxyModel(this); + auto proxy = new QSortFilterProxyModel(this); + proxy->setRecursiveFilteringEnabled(true); proxy->setSourceModel(m_model); ui->typeTreeView->setModel(proxy); ui->typeTreeView->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); connect(ui->typeTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &TypeView::selectionChanged); connect(ui->searchLineEdit, &QLineEdit::textChanged, this, [proxy](const QString &text) { proxy->setFilterFixedString(text); }); connect(ui->detailsView, &QTextBrowser::anchorClicked, this, [](const QUrl &url) { if (url.scheme() == QLatin1String("code")) CodeNavigator::goTo(url); }); } TypeView::~TypeView() = default; void TypeView::setFileSet(ElfFileSet* fileSet) { m_fileSet = fileSet; if (isVisible()) { m_model->setFileSet(m_fileSet); if (m_model->hasInvalidDies()) QMessageBox::warning(this, tr("Invalid DWARF entries"), tr("An error occurred while reading DWARF data of some ELF objects, the tree will be incomplete.")); } } void TypeView::showEvent(QShowEvent* event) { if (isVisible() && m_model->rowCount() == 0 && m_fileSet) { const auto res = QMessageBox::question(this, tr("Compute Type Tree"), tr("Computing the type tree from DWARF data can take up to several minutes in which the application will not respond, and use up to 1.5GB of memory. Proceed anyway?"), QMessageBox::Yes, QMessageBox::Cancel); if (res == QMessageBox::Yes) { m_model->setFileSet(m_fileSet); if (m_model->hasInvalidDies()) QMessageBox::warning(this, tr("Invalid DWARF entries"), tr("An error occurred while reading DWARF data of some ELF objects, the tree will be incomplete.")); } } QWidget::showEvent(event); } void TypeView::selectionChanged(const QItemSelection& selection) { if (selection.isEmpty()) ui->detailsView->clear(); const QModelIndex index = selection.first().topLeft(); ui->detailsView->setHtml(index.data(TypeModel::DetailRole).toString()); }