diff options
Diffstat (limited to 'plugins/warp/ui/matches.cpp')
| -rw-r--r-- | plugins/warp/ui/matches.cpp | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/plugins/warp/ui/matches.cpp b/plugins/warp/ui/matches.cpp new file mode 100644 index 00000000..fad729d6 --- /dev/null +++ b/plugins/warp/ui/matches.cpp @@ -0,0 +1,164 @@ +#include <QGridLayout> +#include <QHeaderView> + +#include "matches.h" + +#include <QClipboard> +#include <QFormLayout> + +#include "theme.h" +#include "warp.h" +#include "shared/misc.h" + +WarpCurrentFunctionWidget::WarpCurrentFunctionWidget(FunctionRef current) +{ + // NOTE: Might be nullptr if the no selected function. + m_current = current; + + // Create the QT stuff + QGridLayout *layout = new QGridLayout(this); + layout->setContentsMargins(2, 2, 2, 2); + layout->setSpacing(2); + auto newPalette = palette(); + newPalette.setColor(QPalette::Window, getThemeColor(SidebarWidgetBackgroundColor)); + setAutoFillBackground(true); + setPalette(newPalette); + + // TODO: Split horizontally if the widget is displayed in a sidebar that is vertically challenged. + m_splitter = new QSplitter(Qt::Vertical); + m_splitter->setContentsMargins(0, 0, 0, 0); + + // Add a widget to display the matches. + m_tableWidget = new WarpFunctionTableWidget(this); + m_tableWidget->setContentsMargins(0, 0, 0, 0); + m_splitter->addWidget(m_tableWidget); + + // Add a widget to display the info about the selected function match. + m_infoWidget = new WarpFunctionInfoWidget(this); + m_infoWidget->setContentsMargins(0, 0, 0, 0); + m_splitter->addWidget(m_infoWidget); + + layout->addWidget(m_splitter, 1, 0, 1, 5); + setLayout(layout); + + m_tableWidget->RegisterContextMenuAction("Apply", [this](WarpFunctionItem *item, std::optional<uint64_t>) { + if (item == nullptr) + return; + Warp::Ref<Warp::Function> selectedFunction = item->GetFunction(); + if (!selectedFunction) + return; + selectedFunction->Apply(*m_current); + // Update analysis so that the selected function shows. + m_current->GetView()->UpdateAnalysis(); + // So it shows visually as selected. + m_tableWidget->GetModel()->SetMatchedFunction(selectedFunction); + }); + m_tableWidget->RegisterContextMenuAction("Search for Source", + [this](WarpFunctionItem *item, std::optional<uint64_t>) { + // Apply the source as the filter. + if (const auto source = item->GetSource(); source) + m_tableWidget->setFilter(source->ToString()); + }); + + connect(m_tableWidget->GetTableView(), &QTableView::clicked, this, + [this](const QModelIndex &index) { + if (m_current == nullptr) + return; + if (!index.isValid()) + return; + const QModelIndex sourceIndex = m_tableWidget->GetProxyModel()->mapToSource(index); + if (!sourceIndex.isValid()) + return; + auto selectedItem = m_tableWidget->GetModel()->GetItem(sourceIndex); + // Access the first column in the row + if (!selectedItem) + return; + m_infoWidget->SetFunction(selectedItem->GetFunction()); + m_infoWidget->UpdateInfo(); + }); + + + connect(m_tableWidget->GetTableView(), &QTableView::doubleClicked, this, [=](const QModelIndex &index) { + if (m_current == nullptr) + return; + // Get the selected row for the given index. + if (!index.isValid()) + return; + const QModelIndex sourceIndex = m_tableWidget->GetProxyModel()->mapToSource(index); + if (!sourceIndex.isValid()) + return; + auto selectedItem = m_tableWidget->GetModel()->GetItem(sourceIndex); + // Access the first column in the row + if (!selectedItem) + return; + Warp::Ref<Warp::Function> selectedFunction = selectedItem->GetFunction(); + + // Actually apply the newly selected function. + selectedFunction->Apply(*m_current); + + // Update analysis so that the selected function shows. + m_current->GetView()->UpdateAnalysis(); + + // So it shows visually as selected. + m_tableWidget->GetModel()->SetMatchedFunction(selectedFunction); + }); +} + +void WarpCurrentFunctionWidget::SetCurrentFunction(FunctionRef current) +{ + if (m_current == current) + return; + m_current = current; + m_infoWidget->SetAnalysisFunction(m_current); + UpdateMatches(); +} + +void WarpCurrentFunctionWidget::UpdateMatches() +{ + if (!m_current) + return; + const auto guid = Warp::GetAnalysisFunctionGUID(*m_current); + if (!guid.has_value()) + return; + + // Set the matched function for highlighting. + Warp::Ref<Warp::Function> matchedFunction = Warp::Function::GetMatched(*m_current); + m_tableWidget->GetModel()->SetMatchedFunction(matchedFunction); + + // We swapped functions, reset the info widget to the default state with new analysis function. + m_infoWidget->SetFunction(matchedFunction); + m_infoWidget->UpdateInfo(); + + Warp::Ref<Warp::Target> target = Warp::Target::FromPlatform(*m_current->GetPlatform()); + + // Add all the possible matches for the current function to the model. + QVector<WarpFunctionItem *> matches; + bool matchedFuncAdded = false; + // TODO: When we add in the networked container we need to update this stuff on a separate thread and show a spinny thing. + for (const auto &container: Warp::Container::All()) + { + for (const auto &source: container->GetSourcesWithFunctionGUID(*target, guid.value())) + { + for (const auto &function: container->GetFunctionsWithGUID(*target, source, guid.value())) + { + // TODO: This does not work. + if (matchedFunction && BNWARPFunctionsEqual(function->m_object, matchedFunction->m_object)) + matchedFuncAdded = true; + auto item = new WarpFunctionItem(function, m_current); + item->SetContainer(container); + item->SetSource(source); + matches.emplace_back(item); + } + } + } + + // Add the matched function unconditionally, assuming it has not been found in a container. + // NOTE: This happens when you load from a database for example. + if (matchedFunction && !matchedFuncAdded) + { + auto item = new WarpFunctionItem(matchedFunction, m_current); + matches.emplace_back(item); + } + + m_tableWidget->SetFunctions(matches); +} |
