Phase 5 sub-commit 1: DevConsole + child-output capture + Ctrl+` toggle
BackendConnection now captures the bundled FrankenPHP child's merged stdout+stderr into a 500-line ring buffer, mirrors each line through qCInfo(lcBundled) so terminal users still see logs, and exposes childLogTail() / childLogLine for QML. DevConsole.qml is an opt-in monospaced viewer with auto-scroll + clear that the skeleton and the todo example bind to Ctrl+`. Dev mode (when BRIDGE_URL is set, no bundled child) renders an explanatory hint. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -261,7 +261,11 @@ bool BackendConnection::spawnChild(QString* errorOut)
|
||||
env.insert(QStringLiteral("MERCURE_PUBLISHER_JWT_KEY"), m_jwtSecret);
|
||||
env.insert(QStringLiteral("MERCURE_SUBSCRIBER_JWT_KEY"), m_jwtSecret);
|
||||
m_child->setProcessEnvironment(env);
|
||||
m_child->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
// Capture both streams into a single chronological buffer so the
|
||||
// DevConsole sees stderr (FrankenPHP / Symfony logs) interleaved with
|
||||
// stdout the same way a TTY would. The console keeps still emitting
|
||||
// each line via qCInfo(lcBundled) so terminal users aren't blinded.
|
||||
m_child->setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
// Linux: kernel kills the child if the parent dies for any reason.
|
||||
m_child->setChildProcessModifier([] {
|
||||
@@ -270,6 +274,8 @@ bool BackendConnection::spawnChild(QString* errorOut)
|
||||
|
||||
connect(m_child, &QProcess::finished,
|
||||
this, &BackendConnection::onChildFinished);
|
||||
connect(m_child, &QProcess::readyReadStandardOutput,
|
||||
this, &BackendConnection::onChildOutputReady);
|
||||
|
||||
qCInfo(lcBundled) << "spawning frankenphp on port" << m_port;
|
||||
m_child->start();
|
||||
@@ -296,6 +302,38 @@ void BackendConnection::teardownChild()
|
||||
disconnect(m_child, nullptr, this, nullptr);
|
||||
m_child->deleteLater();
|
||||
m_child = nullptr;
|
||||
m_childLogBuffer.clear();
|
||||
}
|
||||
|
||||
void BackendConnection::onChildOutputReady()
|
||||
{
|
||||
if (!m_child) return;
|
||||
m_childLogBuffer += QString::fromUtf8(m_child->readAllStandardOutput());
|
||||
|
||||
int nl;
|
||||
while ((nl = m_childLogBuffer.indexOf(QLatin1Char('\n'))) >= 0) {
|
||||
QString line = m_childLogBuffer.left(nl);
|
||||
m_childLogBuffer.remove(0, nl + 1);
|
||||
if (line.endsWith(QLatin1Char('\r'))) {
|
||||
line.chop(1);
|
||||
}
|
||||
qCInfo(lcBundled).noquote() << line;
|
||||
m_childLog.enqueue(line);
|
||||
while (m_childLog.size() > kChildLogMax) {
|
||||
m_childLog.dequeue();
|
||||
}
|
||||
emit childLogLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
QStringList BackendConnection::childLogTail() const
|
||||
{
|
||||
QStringList out;
|
||||
out.reserve(m_childLog.size());
|
||||
for (const QString& l : m_childLog) {
|
||||
out.append(l);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void BackendConnection::onChildFinished(int exitCode, QProcess::ExitStatus status)
|
||||
|
||||
Reference in New Issue
Block a user