mirror of
https://github.com/NohamR/Reclass.git
synced 2026-05-10 19:59:21 +00:00
Replace DIA SDK COM-based PDB importer with RawPDB (MolecularMatters) which reads PDB files directly via memory-mapped I/O. Adds File menu "Import PDB..." dialog with type filtering, selection, and progress. - Vendor raw_pdb into third_party/ - Two-phase API: enumeratePdbTypes() + importPdbSelected() - Full recursive import of structs/unions/arrays/pointers/bitfields - PDB import dialog with name filter, select-all, type count - Benchmark: 1654 types from ntkrnlmp.pdb in 16ms - Reorganize import/export files into src/imports/
185 lines
5.5 KiB
C++
185 lines
5.5 KiB
C++
#include "import_pdb_dialog.h"
|
|
#include "import_pdb.h"
|
|
|
|
#include <QVBoxLayout>
|
|
#include <QHBoxLayout>
|
|
#include <QLineEdit>
|
|
#include <QCheckBox>
|
|
#include <QListWidget>
|
|
#include <QLabel>
|
|
#include <QDialogButtonBox>
|
|
#include <QPushButton>
|
|
#include <QFileDialog>
|
|
#include <QMessageBox>
|
|
#include <QApplication>
|
|
|
|
namespace rcx {
|
|
|
|
PdbImportDialog::PdbImportDialog(QWidget* parent)
|
|
: QDialog(parent)
|
|
{
|
|
setWindowTitle("Import from PDB");
|
|
resize(520, 480);
|
|
|
|
auto* layout = new QVBoxLayout(this);
|
|
|
|
// PDB path row
|
|
auto* pathRow = new QHBoxLayout;
|
|
pathRow->addWidget(new QLabel("PDB File:"));
|
|
m_pathEdit = new QLineEdit;
|
|
m_pathEdit->setPlaceholderText("Select a PDB file...");
|
|
pathRow->addWidget(m_pathEdit);
|
|
m_browseBtn = new QPushButton("...");
|
|
m_browseBtn->setFixedWidth(32);
|
|
pathRow->addWidget(m_browseBtn);
|
|
layout->addLayout(pathRow);
|
|
|
|
// Filter row
|
|
auto* filterRow = new QHBoxLayout;
|
|
filterRow->addWidget(new QLabel("Filter:"));
|
|
m_filterEdit = new QLineEdit;
|
|
m_filterEdit->setPlaceholderText("Type name filter...");
|
|
m_filterEdit->setEnabled(false);
|
|
filterRow->addWidget(m_filterEdit);
|
|
layout->addLayout(filterRow);
|
|
|
|
// Select all checkbox
|
|
m_selectAll = new QCheckBox("Select All");
|
|
m_selectAll->setEnabled(false);
|
|
layout->addWidget(m_selectAll);
|
|
|
|
// Type list
|
|
m_typeList = new QListWidget;
|
|
m_typeList->setEnabled(false);
|
|
layout->addWidget(m_typeList);
|
|
|
|
// Count label
|
|
m_countLabel = new QLabel("No PDB loaded");
|
|
layout->addWidget(m_countLabel);
|
|
|
|
// Buttons
|
|
m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
|
m_buttons->button(QDialogButtonBox::Ok)->setText("Import");
|
|
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(false);
|
|
layout->addWidget(m_buttons);
|
|
|
|
connect(m_browseBtn, &QPushButton::clicked, this, &PdbImportDialog::browsePdb);
|
|
connect(m_pathEdit, &QLineEdit::returnPressed, this, &PdbImportDialog::loadPdb);
|
|
connect(m_filterEdit, &QLineEdit::textChanged, this, &PdbImportDialog::filterChanged);
|
|
connect(m_selectAll, &QCheckBox::toggled, this, &PdbImportDialog::selectAllToggled);
|
|
connect(m_typeList, &QListWidget::itemChanged, this, &PdbImportDialog::updateSelectionCount);
|
|
connect(m_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
|
connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
|
}
|
|
|
|
QString PdbImportDialog::pdbPath() const {
|
|
return m_pathEdit->text();
|
|
}
|
|
|
|
QVector<uint32_t> PdbImportDialog::selectedTypeIndices() const {
|
|
QVector<uint32_t> result;
|
|
for (int i = 0; i < m_typeList->count(); i++) {
|
|
auto* item = m_typeList->item(i);
|
|
if (item->checkState() == Qt::Checked) {
|
|
uint32_t typeIndex = item->data(Qt::UserRole).toUInt();
|
|
result.append(typeIndex);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void PdbImportDialog::browsePdb() {
|
|
QString path = QFileDialog::getOpenFileName(this,
|
|
"Select PDB File", {},
|
|
"PDB Files (*.pdb);;All Files (*)");
|
|
if (path.isEmpty()) return;
|
|
m_pathEdit->setText(path);
|
|
loadPdb();
|
|
}
|
|
|
|
void PdbImportDialog::loadPdb() {
|
|
QString path = m_pathEdit->text();
|
|
if (path.isEmpty()) return;
|
|
|
|
m_typeList->clear();
|
|
m_allTypes.clear();
|
|
m_countLabel->setText("Loading...");
|
|
m_typeList->setEnabled(false);
|
|
m_filterEdit->setEnabled(false);
|
|
m_selectAll->setEnabled(false);
|
|
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(false);
|
|
QApplication::processEvents();
|
|
|
|
QString error;
|
|
QVector<PdbTypeInfo> types = enumeratePdbTypes(path, &error);
|
|
|
|
if (types.isEmpty()) {
|
|
m_countLabel->setText(error.isEmpty() ? "No types found" : error);
|
|
return;
|
|
}
|
|
|
|
m_allTypes.reserve(types.size());
|
|
for (const auto& t : types) {
|
|
TypeItem item;
|
|
item.typeIndex = t.typeIndex;
|
|
item.name = t.name;
|
|
item.childCount = t.childCount;
|
|
item.isUnion = t.isUnion;
|
|
m_allTypes.append(item);
|
|
}
|
|
|
|
// Sort by name
|
|
std::sort(m_allTypes.begin(), m_allTypes.end(),
|
|
[](const TypeItem& a, const TypeItem& b) { return a.name < b.name; });
|
|
|
|
m_filterEdit->setEnabled(true);
|
|
m_selectAll->setEnabled(true);
|
|
m_typeList->setEnabled(true);
|
|
populateList();
|
|
}
|
|
|
|
void PdbImportDialog::populateList() {
|
|
m_typeList->blockSignals(true);
|
|
m_typeList->clear();
|
|
|
|
QString filter = m_filterEdit->text();
|
|
bool selectAll = m_selectAll->isChecked();
|
|
|
|
for (const auto& t : m_allTypes) {
|
|
if (!filter.isEmpty() && !t.name.contains(filter, Qt::CaseInsensitive))
|
|
continue;
|
|
|
|
QString label = QStringLiteral("%1 (%2 fields)")
|
|
.arg(t.name).arg(t.childCount);
|
|
auto* item = new QListWidgetItem(label, m_typeList);
|
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
|
item->setCheckState(selectAll ? Qt::Checked : Qt::Unchecked);
|
|
item->setData(Qt::UserRole, t.typeIndex);
|
|
}
|
|
|
|
m_typeList->blockSignals(false);
|
|
updateSelectionCount();
|
|
}
|
|
|
|
void PdbImportDialog::filterChanged(const QString&) {
|
|
populateList();
|
|
}
|
|
|
|
void PdbImportDialog::selectAllToggled(bool) {
|
|
populateList();
|
|
}
|
|
|
|
void PdbImportDialog::updateSelectionCount() {
|
|
int checked = 0;
|
|
int total = m_typeList->count();
|
|
for (int i = 0; i < total; i++) {
|
|
if (m_typeList->item(i)->checkState() == Qt::Checked)
|
|
checked++;
|
|
}
|
|
m_countLabel->setText(QStringLiteral("%1 of %2 types selected")
|
|
.arg(checked).arg(m_allTypes.size()));
|
|
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(checked > 0);
|
|
}
|
|
|
|
} // namespace rcx
|