diff options
| author | Alexander Taylor <alex@vector35.com> | 2025-04-02 21:14:20 -0400 |
|---|---|---|
| committer | Alexander Taylor <alex@vector35.com> | 2025-04-02 21:21:53 -0400 |
| commit | 67e5ac0aa51db4fd52da786a6227c8bc649814e5 (patch) | |
| tree | 88971634c3dacc6da14b4b0b58f8bdb068df5e33 /view/sharedcache | |
| parent | 1b32a95b3a88567b349e1d3a57dea2fea9f42961 (diff) | |
Add context menu for shared cache view.
Also addresses some lints that I thought were possibly worth it.
Diffstat (limited to 'view/sharedcache')
| -rw-r--r-- | view/sharedcache/ui/dsctriage.cpp | 73 | ||||
| -rw-r--r-- | view/sharedcache/ui/dsctriage.h | 9 |
2 files changed, 75 insertions, 7 deletions
diff --git a/view/sharedcache/ui/dsctriage.cpp b/view/sharedcache/ui/dsctriage.cpp index 91e1d24c..642fc5df 100644 --- a/view/sharedcache/ui/dsctriage.cpp +++ b/view/sharedcache/ui/dsctriage.cpp @@ -53,7 +53,7 @@ DSCTriageView::DSCTriageView(QWidget* parent, BinaryViewRef data) : QWidget(pare QWidget* defaultWidget = nullptr; - auto loadImagesWithAddr = [this](const std::vector<uint64_t>& addresses) { + auto loadImagesWithAddr = [this](const std::vector<uint64_t>& addresses, bool includeDependencies = false) { auto controller = SharedCacheController::GetController(*this->m_data); if (!controller) return; @@ -64,7 +64,24 @@ DSCTriageView::DSCTriageView(QWidget* parent, BinaryViewRef data) : QWidget(pare auto image = controller->GetImageContaining(addr); // Only try to load if we have not already. if (image.has_value() && !controller->IsImageLoaded(*image)) + { images.insert({image->headerAddress, *image}); + + // TODO: We currently only add direct dependencies, may want to make the depth configurable? + if (includeDependencies) + { + auto dependencies = controller->GetImageDependencies(*image); + for (const auto& depName : dependencies) + { + auto depImage = controller->GetImageWithName(depName); + if (depImage.has_value() && !controller->IsImageLoaded(*depImage)) + { + images.insert({depImage->headerAddress, *depImage}); + } + } + } + } + } // Don't create a worker action if we don't have any images. @@ -94,14 +111,62 @@ DSCTriageView::DSCTriageView(QWidget* parent, BinaryViewRef data) : QWidget(pare }; // Tab: Images - auto loadImageTable = new FilterableTableView; + auto loadImageTable = new FilterableTableView(this); { m_imageModel = new QStandardItemModel(0, 3, loadImageTable); m_imageModel->setHorizontalHeaderLabels({"Address", "Loaded", "Name"}); // Apply custom column styling loadImageTable->setItemDelegateForColumn(0, new AddressColorDelegate(loadImageTable)); - loadImageTable->setItemDelegateForColumn(1, new LoadedDelegate()); + loadImageTable->setItemDelegateForColumn(1, new LoadedDelegate(loadImageTable)); + + // Context menu + loadImageTable->setContextMenuPolicy(Qt::CustomContextMenu); + connect(loadImageTable, &QWidget::customContextMenuRequested, [loadImageTable, loadImagesWithAddr](const QPoint &pos) { + QMenu contextMenu(tr("Load Image Actions"), loadImageTable); + + // Get number of selected images + auto selected = loadImageTable->selectionModel()->selectedRows(); + int selectedCount = 0; + std::vector<uint64_t> addresses; + for (const auto& idx : selected) + { + // Skip rows hidden by the filter + if (loadImageTable->isRowHidden(idx.row())) + continue; + addresses.push_back(idx.data().toString().toULongLong(nullptr, 16)); + selectedCount++; + } + + QAction noSelectionAction("No Images Selected", loadImageTable); + QAction loadImagesAction("", loadImageTable); + QAction loadImagesWithDepsAction("", loadImageTable); + if (selectedCount == 0) + { + noSelectionAction.setEnabled(false); + contextMenu.addAction(&noSelectionAction); + } + else + { + // Format action text for loading selected images + QString loadActionText = (selectedCount == 1) ? "Load Selected Image" : QString("Load %1 Selected Images").arg(selectedCount); + loadImagesAction.setText(loadActionText); + connect(&loadImagesAction, &QAction::triggered, [loadImagesWithAddr, addresses]() { + loadImagesWithAddr(addresses, false); + }); + contextMenu.addAction(&loadImagesAction); + + // Format action text for loading selected images with dependencies + QString loadWithDepsActionText = (selectedCount == 1) ? "Load Selected Image and Dependencies" : QString("Load %1 Selected Images and Dependencies").arg(selectedCount); + loadImagesWithDepsAction.setText(loadWithDepsActionText); + connect(&loadImagesWithDepsAction, &QAction::triggered, [loadImagesWithAddr, addresses]() { + loadImagesWithAddr(addresses, true); + }); + contextMenu.addAction(&loadImagesWithDepsAction); + } + + contextMenu.exec(loadImageTable->viewport()->mapToGlobal(pos)); + }); auto loadImageButton = new QPushButton(); connect(loadImageButton, &QPushButton::clicked, @@ -110,7 +175,7 @@ DSCTriageView::DSCTriageView(QWidget* parent, BinaryViewRef data) : QWidget(pare std::vector<uint64_t> addresses; for (const auto& idx : selected) { - // Skip rows hidden by the filter. + // Skip rows hidden by the filter if (loadImageTable->isRowHidden(idx.row())) continue; addresses.push_back(idx.data().toString().toULongLong(nullptr, 16)); diff --git a/view/sharedcache/ui/dsctriage.h b/view/sharedcache/ui/dsctriage.h index edab8358..ae49bc8e 100644 --- a/view/sharedcache/ui/dsctriage.h +++ b/view/sharedcache/ui/dsctriage.h @@ -23,7 +23,7 @@ class AddressColorDelegate : public QStyledItemDelegate { public: - AddressColorDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {} + explicit AddressColorDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {} void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override { @@ -101,7 +101,7 @@ public: bool eventFilter(QObject* obj, QEvent* event) override { if (event->type() == QEvent::KeyPress) { - QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); + auto* keyEvent = dynamic_cast<QKeyEvent*>(event); if (keyEvent->key() == Qt::Key_Escape) { clearSelection(); return true; @@ -161,7 +161,10 @@ public: class LoadedDelegate : public QItemDelegate { Q_OBJECT + public: + explicit LoadedDelegate(QObject* parent = nullptr) : QItemDelegate(parent) {} + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { @@ -202,7 +205,7 @@ public: { Q_UNUSED(option); Q_UNUSED(index); - return QSize(50, 24); + return {50, 24}; } void setEditorData(QWidget *editor, const QModelIndex &index) const override |
