mirror of
https://github.com/NohamR/Reclass.git
synced 2026-05-10 19:59:21 +00:00
feat: option to have class opening brace on new line
This commit is contained in:
@@ -25,6 +25,7 @@ struct ComposeState {
|
||||
bool baseEmitted = false; // only first root struct shows base address
|
||||
bool compactColumns = false; // compact column mode: cap type width, overflow long types
|
||||
bool treeLines = false; // draw Unicode tree connectors in indentation
|
||||
bool braceWrap = false; // opening brace on its own line
|
||||
QVector<bool> siblingStack; // per-depth: true = more siblings follow at this level
|
||||
uint64_t currentPtrBase = 0; // absolute addr of current pointer expansion target
|
||||
|
||||
@@ -319,7 +320,24 @@ void composeParent(ComposeState& state, const NodeTree& tree,
|
||||
lm.effectiveNameW = nameW;
|
||||
headerText = fmt::fmtStructHeader(node, depth, node.collapsed, typeW, nameW, state.compactColumns);
|
||||
}
|
||||
state.emitLine(headerText, lm);
|
||||
// Brace wrapping: move trailing '{' to its own line
|
||||
if (state.braceWrap && !node.collapsed && headerText.endsWith(QChar('{'))) {
|
||||
headerText.chop(1);
|
||||
// Remove trailing separator spaces
|
||||
while (headerText.endsWith(' ')) headerText.chop(1);
|
||||
state.emitLine(headerText, lm);
|
||||
// Emit standalone brace line
|
||||
LineMeta braceLm;
|
||||
braceLm.nodeIdx = nodeIdx;
|
||||
braceLm.nodeId = node.id;
|
||||
braceLm.depth = depth;
|
||||
braceLm.lineKind = LineKind::Header;
|
||||
braceLm.foldLevel = computeFoldLevel(depth, true);
|
||||
braceLm.markerMask = (1u << M_STRUCT_BG);
|
||||
state.emitLine(fmt::indent(depth) + QStringLiteral("{"), braceLm);
|
||||
} else {
|
||||
state.emitLine(headerText, lm);
|
||||
}
|
||||
}
|
||||
|
||||
if (!node.collapsed || isArrayChild || isRootHeader) {
|
||||
@@ -840,9 +858,26 @@ void composeNode(ComposeState& state, const NodeTree& tree,
|
||||
lm.effectiveTypeW = ptrOverflow ? ptrTypeOverride.size() : typeW;
|
||||
lm.effectiveNameW = nameW;
|
||||
lm.pointerTargetName = ptrTargetName;
|
||||
state.emitLine(fmt::fmtPointerHeader(node, depth, effectiveCollapsed,
|
||||
prov, absAddr, ptrTypeOverride,
|
||||
typeW, nameW, state.compactColumns), lm);
|
||||
{
|
||||
QString ptrText = fmt::fmtPointerHeader(node, depth, effectiveCollapsed,
|
||||
prov, absAddr, ptrTypeOverride,
|
||||
typeW, nameW, state.compactColumns);
|
||||
if (state.braceWrap && !effectiveCollapsed && ptrText.endsWith(QChar('{'))) {
|
||||
ptrText.chop(1);
|
||||
while (ptrText.endsWith(' ')) ptrText.chop(1);
|
||||
state.emitLine(ptrText, lm);
|
||||
LineMeta braceLm;
|
||||
braceLm.nodeIdx = nodeIdx;
|
||||
braceLm.nodeId = node.id;
|
||||
braceLm.depth = depth;
|
||||
braceLm.lineKind = LineKind::Header;
|
||||
braceLm.foldLevel = computeFoldLevel(depth, true);
|
||||
braceLm.markerMask = lm.markerMask;
|
||||
state.emitLine(fmt::indent(depth) + QStringLiteral("{"), braceLm);
|
||||
} else {
|
||||
state.emitLine(ptrText, lm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!effectiveCollapsed) {
|
||||
@@ -936,10 +971,11 @@ void composeNode(ComposeState& state, const NodeTree& tree,
|
||||
} // anonymous namespace
|
||||
|
||||
ComposeResult compose(const NodeTree& tree, const Provider& prov, uint64_t viewRootId,
|
||||
bool compactColumns, bool treeLines) {
|
||||
bool compactColumns, bool treeLines, bool braceWrap) {
|
||||
ComposeState state;
|
||||
state.compactColumns = compactColumns;
|
||||
state.treeLines = treeLines;
|
||||
state.braceWrap = braceWrap;
|
||||
|
||||
// Precompute parent→children map
|
||||
for (int i = 0; i < tree.nodes.size(); i++)
|
||||
@@ -1082,6 +1118,18 @@ ComposeResult compose(const NodeTree& tree, const Provider& prov, uint64_t viewR
|
||||
state.emitLine(cmdRowText, lm);
|
||||
}
|
||||
|
||||
// Brace wrapping: emit standalone "{" after CommandRow
|
||||
if (state.braceWrap) {
|
||||
LineMeta braceLm;
|
||||
braceLm.nodeIdx = -1;
|
||||
braceLm.nodeId = kCommandRowId;
|
||||
braceLm.depth = 0;
|
||||
braceLm.lineKind = LineKind::Header;
|
||||
braceLm.foldLevel = SC_FOLDLEVELBASE;
|
||||
braceLm.markerMask = 0;
|
||||
state.emitLine(QStringLiteral("{"), braceLm);
|
||||
}
|
||||
|
||||
const QVector<int>& roots = childIndices(state, 0);
|
||||
|
||||
for (int idx : roots) {
|
||||
|
||||
@@ -73,8 +73,8 @@ RcxDocument::RcxDocument(QObject* parent)
|
||||
}
|
||||
|
||||
ComposeResult RcxDocument::compose(uint64_t viewRootId, bool compactColumns,
|
||||
bool treeLines) const {
|
||||
return rcx::compose(tree, *provider, viewRootId, compactColumns, treeLines);
|
||||
bool treeLines, bool braceWrap) const {
|
||||
return rcx::compose(tree, *provider, viewRootId, compactColumns, treeLines, braceWrap);
|
||||
}
|
||||
|
||||
bool RcxDocument::save(const QString& path) {
|
||||
@@ -558,9 +558,9 @@ void RcxController::refresh() {
|
||||
|
||||
// Compose against snapshot provider if active, otherwise real provider
|
||||
if (m_snapshotProv)
|
||||
m_lastResult = rcx::compose(m_doc->tree, *m_snapshotProv, m_viewRootId, m_compactColumns, m_treeLines);
|
||||
m_lastResult = rcx::compose(m_doc->tree, *m_snapshotProv, m_viewRootId, m_compactColumns, m_treeLines, m_braceWrap);
|
||||
else
|
||||
m_lastResult = m_doc->compose(m_viewRootId, m_compactColumns, m_treeLines);
|
||||
m_lastResult = m_doc->compose(m_viewRootId, m_compactColumns, m_treeLines, m_braceWrap);
|
||||
|
||||
s_composeDoc = nullptr;
|
||||
|
||||
@@ -2444,6 +2444,7 @@ void RcxController::updateCommandRow() {
|
||||
.arg(elide(src, 40), elide(addr, 24));
|
||||
|
||||
// Build row 2: root class type + name (uses current view root)
|
||||
QString brace = m_braceWrap ? QString() : QStringLiteral(" {");
|
||||
QString row2;
|
||||
if (m_viewRootId != 0) {
|
||||
int vi = m_doc->tree.indexOfId(m_viewRootId);
|
||||
@@ -2451,8 +2452,8 @@ void RcxController::updateCommandRow() {
|
||||
const auto& n = m_doc->tree.nodes[vi];
|
||||
QString keyword = n.resolvedClassKeyword();
|
||||
QString className = n.structTypeName.isEmpty() ? n.name : n.structTypeName;
|
||||
row2 = QStringLiteral("%1 %2 {")
|
||||
.arg(keyword, className.isEmpty() ? QStringLiteral("NoName") : className);
|
||||
row2 = QStringLiteral("%1 %2%3")
|
||||
.arg(keyword, className.isEmpty() ? QStringLiteral("NoName") : className, brace);
|
||||
}
|
||||
}
|
||||
if (row2.isEmpty()) {
|
||||
@@ -2462,14 +2463,14 @@ void RcxController::updateCommandRow() {
|
||||
if (n.parentId == 0 && n.kind == NodeKind::Struct) {
|
||||
QString keyword = n.resolvedClassKeyword();
|
||||
QString className = n.structTypeName.isEmpty() ? n.name : n.structTypeName;
|
||||
row2 = QStringLiteral("%1 %2 {")
|
||||
.arg(keyword, className.isEmpty() ? QStringLiteral("NoName") : className);
|
||||
row2 = QStringLiteral("%1 %2%3")
|
||||
.arg(keyword, className.isEmpty() ? QStringLiteral("NoName") : className, brace);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (row2.isEmpty())
|
||||
row2 = QStringLiteral("struct NoName {");
|
||||
row2 = QStringLiteral("struct NoName") + brace;
|
||||
|
||||
QString combined = QStringLiteral("[\u25B8] ") + row + QStringLiteral(" ") + row2;
|
||||
|
||||
@@ -3261,6 +3262,11 @@ void RcxController::setTreeLines(bool v) {
|
||||
refresh();
|
||||
}
|
||||
|
||||
void RcxController::setBraceWrap(bool v) {
|
||||
m_braceWrap = v;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void RcxController::setupAutoRefresh() {
|
||||
int ms = QSettings("Reclass", "Reclass").value("refreshMs", 660).toInt();
|
||||
m_refreshTimer = new QTimer(this);
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
}
|
||||
|
||||
ComposeResult compose(uint64_t viewRootId = 0, bool compactColumns = false,
|
||||
bool treeLines = false) const;
|
||||
bool treeLines = false, bool braceWrap = false) const;
|
||||
bool save(const QString& path);
|
||||
bool load(const QString& path);
|
||||
void loadData(const QString& binaryPath);
|
||||
@@ -130,6 +130,7 @@ public:
|
||||
void setRefreshInterval(int ms);
|
||||
void setCompactColumns(bool v);
|
||||
void setTreeLines(bool v);
|
||||
void setBraceWrap(bool v);
|
||||
void resetProvider();
|
||||
|
||||
// MCP bridge accessors
|
||||
@@ -169,6 +170,7 @@ private:
|
||||
bool m_suppressRefresh = false;
|
||||
bool m_compactColumns = false;
|
||||
bool m_treeLines = false;
|
||||
bool m_braceWrap = false;
|
||||
uint64_t m_viewRootId = 0;
|
||||
|
||||
// ── Saved sources for quick-switch ──
|
||||
|
||||
@@ -1031,6 +1031,7 @@ namespace fmt {
|
||||
// ── Compose function forward declaration ──
|
||||
|
||||
ComposeResult compose(const NodeTree& tree, const Provider& prov, uint64_t viewRootId = 0,
|
||||
bool compactColumns = false, bool treeLines = false);
|
||||
bool compactColumns = false, bool treeLines = false,
|
||||
bool braceWrap = false);
|
||||
|
||||
} // namespace rcx
|
||||
|
||||
@@ -1450,6 +1450,7 @@ QDockWidget* MainWindow::createTab(RcxDocument* doc) {
|
||||
// Apply global compact columns setting to new tab
|
||||
ctrl->setCompactColumns(QSettings("Reclass", "Reclass").value("compactColumns", true).toBool());
|
||||
ctrl->setTreeLines(QSettings("Reclass", "Reclass").value("treeLines", false).toBool());
|
||||
ctrl->setBraceWrap(QSettings("Reclass", "Reclass").value("braceWrap", false).toBool());
|
||||
|
||||
// Give every controller the shared document list for cross-tab type visibility
|
||||
ctrl->setProjectDocuments(&m_allDocs);
|
||||
@@ -2182,6 +2183,7 @@ void MainWindow::showOptionsDialog() {
|
||||
current.autoStartMcp = QSettings("Reclass", "Reclass").value("autoStartMcp", true).toBool();
|
||||
current.refreshMs = QSettings("Reclass", "Reclass").value("refreshMs", 660).toInt();
|
||||
current.generatorAsserts = QSettings("Reclass", "Reclass").value("generatorAsserts", false).toBool();
|
||||
current.braceWrap = QSettings("Reclass", "Reclass").value("braceWrap", false).toBool();
|
||||
|
||||
OptionsDialog dlg(current, this);
|
||||
if (dlg.exec() != QDialog::Accepted) return; // OptionsDialog doesn't apply anything. Only apply on OK
|
||||
@@ -2216,6 +2218,12 @@ void MainWindow::showOptionsDialog() {
|
||||
|
||||
if (r.generatorAsserts != current.generatorAsserts)
|
||||
QSettings("Reclass", "Reclass").setValue("generatorAsserts", r.generatorAsserts);
|
||||
|
||||
if (r.braceWrap != current.braceWrap) {
|
||||
QSettings("Reclass", "Reclass").setValue("braceWrap", r.braceWrap);
|
||||
for (auto& tab : m_tabs)
|
||||
tab.ctrl->setBraceWrap(r.braceWrap);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setEditorFont(const QString& fontName) {
|
||||
|
||||
@@ -122,6 +122,10 @@ OptionsDialog::OptionsDialog(const OptionsResult& current, QWidget* parent)
|
||||
m_showIconCheck->setChecked(current.showIcon);
|
||||
visualLayout->addRow(m_showIconCheck);
|
||||
|
||||
m_braceWrapCheck = new QCheckBox("Opening brace on new line");
|
||||
m_braceWrapCheck->setChecked(current.braceWrap);
|
||||
visualLayout->addRow(m_braceWrapCheck);
|
||||
|
||||
generalLayout->addWidget(visualGroup);
|
||||
generalLayout->addStretch();
|
||||
|
||||
@@ -212,6 +216,7 @@ OptionsResult OptionsDialog::result() const {
|
||||
r.autoStartMcp = m_autoMcpCheck->isChecked();
|
||||
r.refreshMs = m_refreshSpin->value();
|
||||
r.generatorAsserts = m_assertCheck->isChecked();
|
||||
r.braceWrap = m_braceWrapCheck->isChecked();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ struct OptionsResult {
|
||||
bool autoStartMcp = true;
|
||||
int refreshMs = 660;
|
||||
bool generatorAsserts = false;
|
||||
bool braceWrap = false;
|
||||
};
|
||||
|
||||
class OptionsDialog : public QDialog {
|
||||
@@ -41,6 +42,7 @@ private:
|
||||
QCheckBox* m_autoMcpCheck = nullptr;
|
||||
QSpinBox* m_refreshSpin = nullptr;
|
||||
QCheckBox* m_assertCheck = nullptr;
|
||||
QCheckBox* m_braceWrapCheck = nullptr;
|
||||
|
||||
// searchable keywords per leaf tree item
|
||||
QHash<QTreeWidgetItem*, QStringList> m_pageKeywords;
|
||||
|
||||
Reference in New Issue
Block a user