feat: type selector overhaul, fuzzy search, address parser, value tracking

Redesign type selector popup with fuzzy subsequence matching, per-category
icons, field summary tooltips, compact chips, and pointer target primitives.
Add address expression parser with arithmetic and register support.
Enable track value changes by default.
This commit is contained in:
IChooseYou
2026-02-28 06:59:22 -07:00
committed by IChooseYou
parent 0d73575ea7
commit 6a51c904de
21 changed files with 2489 additions and 592 deletions

View File

@@ -3,6 +3,7 @@
#include <QFont>
#include <QVector>
#include <QString>
#include <QStringList>
#include <cstdint>
#include "core.h"
@@ -26,13 +27,19 @@ enum class TypePopupMode { Root, FieldType, ArrayElement, PointerTarget };
struct TypeEntry {
enum Kind { Primitive, Composite, Section };
enum Category { CatPrimitive, CatType, CatEnum };
Kind entryKind = Primitive;
Category category = CatPrimitive;
NodeKind primitiveKind = NodeKind::Hex8; // valid when entryKind==Primitive
uint64_t structId = 0; // valid when entryKind==Composite
QString displayName;
QString classKeyword; // "struct", "class", "enum" (Composite only)
bool enabled = true; // false = grayed out (visible but not selectable)
int sizeBytes = 0; // size in bytes (for display)
int alignment = 0; // natural alignment in bytes
int fieldCount = 0; // child field count (composite only)
QStringList fieldSummary; // first ~6 fields: "0x00: float x"
};
// ── Parsed type spec (shared between popup filter and inline edit) ──
@@ -58,16 +65,21 @@ public:
void setMode(TypePopupMode mode);
void applyTheme(const Theme& theme);
void setCurrentNodeSize(int bytes);
void setPointerSize(int bytes);
void setModifier(int modId, int arrayCount = 0);
void setTypes(const QVector<TypeEntry>& types, const TypeEntry* current = nullptr);
void popup(const QPoint& globalPos);
/// Show popup instantly with skeleton placeholders; call setTypes() to fill content.
void popupLoading(const QPoint& globalPos);
/// Force native window creation to avoid cold-start delay.
void warmUp();
signals:
void typeSelected(const TypeEntry& entry, const QString& fullText);
void createNewTypeRequested();
void saveRequested();
void dismissed();
protected:
@@ -78,27 +90,35 @@ private:
QLabel* m_titleLabel = nullptr;
QToolButton* m_escLabel = nullptr;
QToolButton* m_createBtn = nullptr;
QToolButton* m_saveBtn = nullptr;
QLineEdit* m_filterEdit = nullptr;
QLabel* m_previewLabel = nullptr;
QListView* m_listView = nullptr;
QStringListModel* m_model = nullptr;
QFrame* m_separator = nullptr;
// Modifier toggles
QWidget* m_modRow = nullptr;
QToolButton* m_btnPlain = nullptr;
QToolButton* m_btnPtr = nullptr;
QToolButton* m_btnDblPtr = nullptr;
QToolButton* m_btnArray = nullptr;
QLineEdit* m_arrayCountEdit = nullptr;
QButtonGroup* m_modGroup = nullptr;
// Category filter checkboxes
QWidget* m_chipRow = nullptr;
QToolButton* m_chipPrim = nullptr;
QToolButton* m_chipTypes = nullptr;
QToolButton* m_chipEnums = nullptr;
QLabel* m_statusLabel = nullptr;
QVector<TypeEntry> m_allTypes;
QVector<TypeEntry> m_filteredTypes;
QVector<QVector<int>> m_matchPositions;
TypeEntry m_currentEntry;
bool m_hasCurrent = false;
TypePopupMode m_mode = TypePopupMode::FieldType;
int m_currentNodeSize = 0;
int m_pointerSize = 8;
bool m_loading = false;
QFont m_font;
void applyFilter(const QString& text);