fix: vergilius fnptr import, remove tab pin, flatten workspace tree, middle-click close

- Fix vergilius_to_rcx.py to detect function pointer syntax (*Name)(params) and emit FuncPtr64
- Re-fetch 85 structs to recover proper field names (697/716 fixed)
- Remove pin button from dock tabs and all pin-related context menu items
- Fix newClass() creating duplicate tabs
- Set workspace tree font to match tab bar (size 10)
- Flatten workspace tree: remove redundant Project group node (VS Code Explorer style)
- Add middle-click to close dock widget tabs
- Allow type chooser to show cross-doc types for root nodes
This commit is contained in:
IChooseYou
2026-03-06 17:39:50 -07:00
committed by IChooseYou
parent 35b3cd9ac1
commit 3ab6affa5e
7 changed files with 2204 additions and 3676 deletions

View File

@@ -1774,8 +1774,9 @@ void MainWindow::setupDockTabBars() {
tabBar->setTabButton(i, QTabBar::RightSide, btns);
}
// Context menu (install only once)
// Middle-click close + context menu (install only once)
if (tabBar->contextMenuPolicy() == Qt::CustomContextMenu) continue;
tabBar->installEventFilter(this);
tabBar->setContextMenuPolicy(Qt::CustomContextMenu);
connect(tabBar, &QTabBar::customContextMenuRequested,
this, [this, tabBar](const QPoint& pos) {
@@ -1790,9 +1791,6 @@ void MainWindow::setupDockTabBars() {
if (!target) return;
auto tabIt = m_tabs.find(target);
auto* btns = qobject_cast<DockTabButtons*>(
tabBar->tabButton(idx, QTabBar::RightSide));
bool isPinned = btns && btns->pinned;
QMenu menu;
@@ -1816,28 +1814,6 @@ void MainWindow::setupDockTabBars() {
});
}
// Close All But Pinned (only if any tab is pinned)
bool anyPinned = false;
for (int i = 0; i < tabBar->count(); ++i) {
auto* b = qobject_cast<DockTabButtons*>(
tabBar->tabButton(i, QTabBar::RightSide));
if (b && b->pinned) { anyPinned = true; break; }
}
if (anyPinned) {
menu.addAction("Close All But Pinned", [this, tabBar]() {
QVector<QDockWidget*> toClose;
for (int i = 0; i < tabBar->count(); ++i) {
auto* b = qobject_cast<DockTabButtons*>(
tabBar->tabButton(i, QTabBar::RightSide));
if (b && b->pinned) continue;
QString title = tabBar->tabText(i);
for (auto* d : m_docDocks)
if (d->windowTitle() == title) { toClose.append(d); break; }
}
for (auto* d : toClose) d->close();
});
}
menu.addSeparator();
// Copy Full Path / Open Containing Folder (only if saved)
@@ -1859,14 +1835,6 @@ void MainWindow::setupDockTabBars() {
menu.addSeparator();
// Pin / Unpin
if (btns) {
QIcon pinIcon = makeIcon(isPinned ? ":/vsicons/pinned.svg"
: ":/vsicons/pin.svg");
menu.addAction(pinIcon, isPinned ? "Unpin Tab" : "Pin Tab",
[btns, isPinned]() { btns->setPinned(!isPinned); });
}
menu.addSeparator();
// New Document Groups (only if >1 tab)
@@ -1918,6 +1886,25 @@ void MainWindow::setupDockTabBars() {
}
}
bool MainWindow::eventFilter(QObject* obj, QEvent* event) {
if (event->type() == QEvent::MouseButtonPress) {
auto* me = static_cast<QMouseEvent*>(event);
if (me->button() == Qt::MiddleButton) {
if (auto* tabBar = qobject_cast<QTabBar*>(obj)) {
int idx = tabBar->tabAt(me->pos());
if (idx >= 0) {
QString title = tabBar->tabText(idx);
for (auto* d : m_docDocks) {
if (d->windowTitle() == title) { d->close(); break; }
}
return true;
}
}
}
}
return QMainWindow::eventFilter(obj, event);
}
// Build a minimal empty struct for new documents
static void buildEmptyStruct(NodeTree& tree, const QString& classKeyword = QString()) {
// ── Enum: bare node with empty enumMembers, no hex children ──
@@ -2008,10 +1995,7 @@ MainWindow::~MainWindow() {
}
void MainWindow::newClass() {
auto* first = project_new(QStringLiteral("class"));
project_new(QStringLiteral("class"));
// Select the first tab
if (first) first->raise();
}
void MainWindow::newStruct() {
@@ -2606,9 +2590,12 @@ void MainWindow::setEditorFont(const QString& fontName) {
}
}
}
// Sync workspace tree font
if (m_workspaceTree)
m_workspaceTree->setFont(f);
// Sync workspace tree font (match tab bar size)
if (m_workspaceTree) {
QFont wf(fontName, 10);
wf.setFixedPitch(true);
m_workspaceTree->setFont(wf);
}
// Sync dock titlebar font
if (m_dockTitleLabel)
m_dockTitleLabel->setFont(f);
@@ -3378,13 +3365,19 @@ void MainWindow::createWorkspaceDock() {
m_workspaceTree->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_workspaceTree->setExpandsOnDoubleClick(false);
m_workspaceTree->setMouseTracking(true);
{
QSettings s("Reclass", "Reclass");
QFont f(s.value("font", "JetBrains Mono").toString(), 10);
f.setFixedPitch(true);
m_workspaceTree->setFont(f);
}
connect(m_workspaceSearch, &QLineEdit::textChanged, this, [this](const QString& text) {
m_workspaceProxy->setFilterFixedString(text);
if (!text.isEmpty())
m_workspaceTree->expandAll();
else
m_workspaceTree->expandToDepth(0);
m_workspaceTree->collapseAll();
});
// Override palette: selection + hover use theme colors (not default blue)
@@ -3402,13 +3395,9 @@ void MainWindow::createWorkspaceDock() {
m_workspaceTree->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_workspaceTree, &QWidget::customContextMenuRequested, this, [this](const QPoint& pos) {
QModelIndex index = m_workspaceTree->indexAt(pos);
if (!index.isValid()) return;
auto structIdVar = index.data(Qt::UserRole + 1);
uint64_t structId = structIdVar.isValid() ? structIdVar.toULongLong() : 0;
// Right-click on "Project" group → New Class / New Struct / New Enum
if (structId == rcx::kGroupSentinel) {
// Right-click on empty area → New Class / New Struct / New Enum
if (!index.isValid()) {
QMenu menu;
auto* actClass = menu.addAction("New Class");
auto* actStruct = menu.addAction("New Struct");
@@ -3420,6 +3409,8 @@ void MainWindow::createWorkspaceDock() {
return;
}
auto structIdVar = index.data(Qt::UserRole + 1);
uint64_t structId = structIdVar.isValid() ? structIdVar.toULongLong() : 0;
if (structId == 0) return;
auto subVar = index.data(Qt::UserRole);
@@ -3524,12 +3515,6 @@ void MainWindow::createWorkspaceDock() {
auto structIdVar = index.data(Qt::UserRole + 1);
uint64_t structId = structIdVar.isValid() ? structIdVar.toULongLong() : 0;
if (structId == rcx::kGroupSentinel) {
// "Project" folder: toggle expand/collapse
m_workspaceTree->setExpanded(index, !m_workspaceTree->isExpanded(index));
return;
}
auto subVar = index.data(Qt::UserRole);
if (!subVar.isValid()) return;
auto* ownerDock = static_cast<QDockWidget*>(subVar.value<void*>());
@@ -3739,7 +3724,6 @@ void MainWindow::rebuildWorkspaceModel() {
tabs.append({ &tab.doc->tree, name, static_cast<void*>(it.key()) });
}
rcx::buildProjectExplorer(m_workspaceModel, tabs);
m_workspaceTree->expandToDepth(0);
}
void MainWindow::addRecentFile(const QString& path) {