Commit 3545c822 authored by hjk's avatar hjk

debugger: put some color into the outputpane

parent 0c03c1b9
......@@ -130,6 +130,13 @@ DebuggerSettings *DebuggerSettings::instance()
item->setDefaultValue(false);
instance->insertItem(UseAlternatingRowColors, item);
item = new SavedAction(instance);
item->setSettingsKey(debugModeGroup, QLatin1String("LogTimeStamps"));
item->setText(tr("Log time stamps"));
item->setCheckable(true);
item->setDefaultValue(false);
instance->insertItem(LogTimeStamps, item);
//
// Locals & Watchers
//
......@@ -155,7 +162,6 @@ DebuggerSettings *DebuggerSettings::instance()
// DebuggingHelper
//
item = new SavedAction(instance);
item->setDefaultValue(true);
item->setSettingsKey(debugModeGroup, QLatin1String("UseDebuggingHelper"));
item->setText(tr("Use debugging helper"));
item->setCheckable(true);
......
......@@ -78,6 +78,7 @@ enum DebuggerActionCode
UseAlternatingRowColors,
AutoQuit,
LockView,
LogTimeStamps,
// Gdb
GdbLocation,
......
......@@ -627,7 +627,7 @@ void DebuggerManager::showStatusMessage(const QString &msg, int timeout)
Q_UNUSED(timeout)
if (Debugger::Constants::Internal::debug)
qDebug() << "STATUS MSG: " << msg;
showDebuggerOutput("status:", msg);
showDebuggerOutput(LogStatus, msg);
m_statusLabel->setText(QLatin1String(" ") + msg);
if (timeout > 0) {
m_statusTimer->setSingleShot(true);
......@@ -908,7 +908,8 @@ static IDebuggerEngine *determineDebuggerEngine(int /* pid */,
#endif
}
void DebuggerManager::startNewDebugger(DebuggerRunControl *runControl, const QSharedPointer<DebuggerStartParameters> &startParameters)
void DebuggerManager::startNewDebugger(DebuggerRunControl *runControl,
const QSharedPointer<DebuggerStartParameters> &startParameters)
{
if (Debugger::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << '\n' << *startParameters;
......@@ -919,7 +920,7 @@ void DebuggerManager::startNewDebugger(DebuggerRunControl *runControl, const QSh
const QString toolChainName = ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChain::ToolChainType>(m_startParameters->toolChainType));
emit debugModeRequested();
showDebuggerOutput(QLatin1String("status:"), tr("Starting debugger for tool chain '%1'...").arg(toolChainName));
showDebuggerOutput(LogStatus, tr("Starting debugger for tool chain '%1'...").arg(toolChainName));
QString errorMessage;
QString settingsIdHint;
......@@ -1452,16 +1453,16 @@ void DebuggerManager::modulesDockToggled(bool on)
//
//////////////////////////////////////////////////////////////////////
void DebuggerManager::showDebuggerOutput(const QString &prefix, const QString &msg)
void DebuggerManager::showDebuggerOutput(int channel, const QString &msg)
{
QTC_ASSERT(m_outputWindow, return);
m_outputWindow->showOutput(prefix, msg);
m_outputWindow->showOutput(channel, msg);
}
void DebuggerManager::showDebuggerInput(const QString &prefix, const QString &msg)
void DebuggerManager::showDebuggerInput(int channel, const QString &msg)
{
QTC_ASSERT(m_outputWindow, return);
m_outputWindow->showInput(prefix, msg);
m_outputWindow->showInput(channel, msg);
}
......
......@@ -53,7 +53,7 @@ class IOptionsPage;
} // namespace Core
namespace TextEditor {
class ITextEditor;
class ITextEditor;
}
namespace Debugger {
......@@ -127,6 +127,16 @@ enum DebuggerStartMode
StartRemote // Start and attach to a remote process
};
enum LogChannel
{
LogInput, // Used for user input
LogOutput,
LogError,
LogStatus, // Used for status changed messages
LogDebug,
LogMisc
};
struct DebuggerStartParameters
{
DebuggerStartParameters();
......@@ -213,8 +223,8 @@ private:
virtual SourceFilesWindow *sourceFileWindow() = 0;
virtual void showApplicationOutput(const QString &data) = 0;
virtual void showDebuggerOutput(const QString &prefix, const QString &msg) = 0;
virtual void showDebuggerInput(const QString &prefix, const QString &msg) = 0;
virtual void showDebuggerOutput(int channel, const QString &msg) = 0;
virtual void showDebuggerInput(int channel, const QString &msg) = 0;
virtual void reloadDisassembler() = 0;
virtual void reloadModules() = 0;
......@@ -309,8 +319,8 @@ public slots:
void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever
private slots:
void showDebuggerOutput(const QString &prefix, const QString &msg);
void showDebuggerInput(const QString &prefix, const QString &msg);
void showDebuggerOutput(int channel, const QString &msg);
void showDebuggerInput(int channel, const QString &msg);
void showApplicationOutput(const QString &data);
void reloadDisassembler();
......
......@@ -29,6 +29,7 @@
#include "debuggeroutputwindow.h"
#include "debuggeractions.h"
#include "debuggermanager.h"
#include <QtCore/QDebug>
......@@ -41,6 +42,7 @@
#include <QtGui/QMenu>
#include <QtGui/QSpacerItem>
#include <QtGui/QSplitter>
#include <QtGui/QSyntaxHighlighter>
#include <QtGui/QTextBlock>
#ifndef GDBDEBUGGERLEAN
......@@ -54,6 +56,73 @@ using namespace Find;
using namespace Debugger::Internal;
static QChar charForChannel(int channel)
{
switch (channel) {
case LogDebug: return 'd';
case LogError: return 'e';
case LogInput: return '<';
case LogOutput: return '>';
case LogStatus: return 's';
case LogMisc:
default: return ' ';
}
}
static LogChannel channelForChar(QChar c)
{
switch (c.unicode()) {
case 'd': return LogDebug;
case 'e': return LogError;
case '<': return LogInput;
case '>': return LogOutput;
case 's': return LogStatus;
default: return LogMisc;
}
}
/////////////////////////////////////////////////////////////////////
//
// OutputHighlighter
//
/////////////////////////////////////////////////////////////////////
class OutputHighlighter : public QSyntaxHighlighter
{
public:
OutputHighlighter(QPlainTextEdit *parent)
: QSyntaxHighlighter(parent->document()), m_parent(parent)
{}
private:
void highlightBlock(const QString &text)
{
QTextCharFormat format;
switch (channelForChar(text.isEmpty() ? QChar() : text.at(0))) {
case LogInput:
format.setForeground(Qt::blue);
setFormat(1, text.size(), format);
break;
case LogStatus:
format.setForeground(Qt::darkGreen);
setFormat(1, text.size(), format);
break;
case LogError:
format.setForeground(Qt::red);
setFormat(1, text.size(), format);
break;
default:
break;
}
QColor base = m_parent->palette().color(QPalette::Base);
format.setForeground(base);
format.setFontPointSize(1);
setFormat(0, 1, format);
}
QPlainTextEdit *m_parent;
};
/////////////////////////////////////////////////////////////////////
//
// InputPane
......@@ -89,6 +158,7 @@ public:
addContextActions(menu);
theDebuggerAction(ExecuteCommand)->setData(textCursor().block().text());
menu->addAction(theDebuggerAction(ExecuteCommand));
menu->addAction(theDebuggerAction(LogTimeStamps));
menu->addSeparator();
menu->addAction(theDebuggerAction(SettingsDialog));
menu->exec(ev->globalPos());
......@@ -176,13 +246,15 @@ class CombinedPane : public DebuggerPane
public:
CombinedPane(QWidget *parent)
: DebuggerPane(parent)
{}
{
(void)new OutputHighlighter(this);
}
public slots:
void gotoResult(int i)
{
QString needle = QString::number(i) + '^';
QString needle2 = QLatin1String("stdout:") + needle;
QString needle2 = QLatin1String(">:") + needle;
QTextCursor cursor(document());
do {
const QString line = cursor.block().text();
......@@ -246,16 +318,17 @@ DebuggerOutputWindow::DebuggerOutputWindow(QWidget *parent)
m_combinedText, SLOT(gotoResult(int)));
};
void DebuggerOutputWindow::showOutput(const QString &prefix, const QString &output)
void DebuggerOutputWindow::showOutput(int channel, const QString &output)
{
if (output.isEmpty())
return;
foreach (QString line, output.split("\n")) {
foreach (QString line, output.split('\n')) {
// FIXME: QTextEdit asserts on really long lines...
const int n = 3000;
const int n = 30000;
if (line.size() > n)
line = line.left(n) + " [...] <cut off>";
m_combinedText->appendPlainText(prefix + line);
if (line != QLatin1String("(gdb) "))
m_combinedText->appendPlainText(charForChannel(channel) + line);
}
QTextCursor cursor = m_combinedText->textCursor();
cursor.movePosition(QTextCursor::End);
......@@ -263,15 +336,15 @@ void DebuggerOutputWindow::showOutput(const QString &prefix, const QString &outp
m_combinedText->ensureCursorVisible();
}
void DebuggerOutputWindow::showInput(const QString &prefix, const QString &input)
void DebuggerOutputWindow::showInput(int channel, const QString &input)
{
Q_UNUSED(prefix);
Q_UNUSED(channel);
m_inputText->appendPlainText(input);
QTextCursor cursor = m_inputText->textCursor();
cursor.movePosition(QTextCursor::End);
m_inputText->setTextCursor(cursor);
m_inputText->ensureCursorVisible();
showOutput("input:", input);
showOutput(LogInput, input);
}
void DebuggerOutputWindow::clearContents()
......
......@@ -59,8 +59,8 @@ public:
public slots:
void clearContents();
void showOutput(const QString &prefix, const QString &output);
void showInput(const QString &prefix, const QString &input);
void showOutput(int channel, const QString &output);
void showInput(int channel, const QString &input);
signals:
void showPage();
......
......@@ -164,11 +164,11 @@ void GdbEngine::initializeConnections()
connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
this, SLOT(readDebugeeOutput(QByteArray)));
connect(this, SIGNAL(gdbOutputAvailable(QString,QString)),
q, SLOT(showDebuggerOutput(QString,QString)),
connect(this, SIGNAL(gdbOutputAvailable(int,QString)),
q, SLOT(showDebuggerOutput(int,QString)),
Qt::QueuedConnection);
connect(this, SIGNAL(gdbInputAvailable(QString,QString)),
q, SLOT(showDebuggerInput(QString,QString)),
connect(this, SIGNAL(gdbInputAvailable(int,QString)),
q, SLOT(showDebuggerInput(int,QString)),
Qt::QueuedConnection);
connect(this, SIGNAL(applicationOutputAvailable(QString)),
q, SLOT(showApplicationOutput(QString)),
......@@ -285,13 +285,13 @@ void GdbEngine::uploadProcError(QProcess::ProcessError error)
void GdbEngine::readUploadStandardOutput()
{
QByteArray ba = m_uploadProc.readAllStandardOutput();
gdbOutputAvailable(_("upload-out:"), QString::fromLocal8Bit(ba, ba.length()));
gdbOutputAvailable(LogOutput, QString::fromLocal8Bit(ba, ba.length()));
}
void GdbEngine::readUploadStandardError()
{
QByteArray ba = m_uploadProc.readAllStandardError();
gdbOutputAvailable(_("upload-err:"), QString::fromLocal8Bit(ba, ba.length()));
gdbOutputAvailable(LogError, QString::fromLocal8Bit(ba, ba.length()));
}
#if 0
......@@ -318,15 +318,16 @@ void GdbEngine::readDebugeeOutput(const QByteArray &data)
void GdbEngine::debugMessage(const QString &msg)
{
emit gdbOutputAvailable(_("debug:"), msg);
emit gdbOutputAvailable(LogDebug, msg);
}
void GdbEngine::handleResponse(const QByteArray &buff)
{
static QTime lastTime;
emit gdbOutputAvailable(_(" "), currentTime());
emit gdbOutputAvailable(_("stdout:"), QString::fromLocal8Bit(buff, buff.length()));
if (theDebuggerBoolSetting(LogTimeStamps))
emit gdbOutputAvailable(LogDebug, currentTime());
emit gdbOutputAvailable(LogOutput, QString::fromLocal8Bit(buff, buff.length()));
#if 0
qDebug() // << "#### start response handling #### "
......@@ -691,7 +692,7 @@ void GdbEngine::flushCommand(GdbCommand &cmd)
m_gdbProc.write(cmd.command.toLatin1() + "\r\n");
//emit gdbInputAvailable(QString(), " " + currentTime());
//emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command);
emit gdbInputAvailable(QString(), cmd.command);
emit gdbInputAvailable(LogInput, cmd.command);
}
void GdbEngine::handleResultRecord(const GdbResultRecord &record)
......@@ -990,7 +991,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
m_waitingForFirstBreakpointToBeHit = false;
// If the executable dies already that early we might get something
// like stdout:49*stopped,reason="exited",exit-code="0177"
// like >49*stopped,reason="exited",exit-code="0177"
// This is handled now above.
qq->notifyInferiorStopped();
......@@ -1032,7 +1033,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
}
// seen on XP after removing a breakpoint while running
// stdout:945*stopped,reason="signal-received",signal-name="SIGTRAP",
// >945*stopped,reason="signal-received",signal-name="SIGTRAP",
// signal-meaning="Trace/breakpoint trap",thread-id="2",
// frame={addr="0x7c91120f",func="ntdll!DbgUiConnectToDbg",
// args=[],from="C:\\WINDOWS\\system32\\ntdll.dll"}
......@@ -1127,7 +1128,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
// file="main.cpp",fullname="/tmp/g/main.cpp",line="37"}
//
// MAC yields sometimes:
// stdout:3661*stopped,time={wallclock="0.00658",user="0.00142",
// >3661*stopped,time={wallclock="0.00658",user="0.00142",
// system="0.00136",start="1218810678.805432",end="1218810678.812011"}
q->resetLocation();
qq->notifyInferiorStopped();
......@@ -1579,7 +1580,7 @@ void GdbEngine::handleStart(const GdbResultRecord &response, const QVariant &)
#else
if (response.resultClass == GdbResultDone) {
// [some leading stdout here]
// stdout:&" Entry point: 0x80831f0 0x08048134 - 0x08048147 is .interp\n"
// >&" Entry point: 0x80831f0 0x08048134 - 0x08048147 is .interp\n"
// [some trailing stdout here]
QString msg = _(response.data.findChild("consolestreamoutput").data());
QRegExp needle(_("\\bEntry point: (0x[0-9a-f]+)\\b"));
......@@ -1775,7 +1776,7 @@ void GdbEngine::setTokenBarrier()
);
}
PENDING_DEBUG("\n--- token barrier ---\n");
emit gdbInputAvailable(QString(), _("--- token barrier ---"));
emit gdbInputAvailable(LogMisc, _("--- token barrier ---"));
m_oldestAcceptableToken = currentToken();
}
......@@ -1905,7 +1906,7 @@ void GdbEngine::sendInsertBreakpoint(int index)
// cmd += _("-c ") + data->condition + ' ';
cmd += where;
#endif
debugMessage(_("Current state: %1").arg(q->status()));
emit gdbOutputAvailable(LogStatus, _("Current state: %1").arg(q->status()));
postCommand(cmd, NeedsStop, CB(handleBreakInsert), index);
}
......@@ -3084,8 +3085,7 @@ void GdbEngine::updateWatchData(const WatchData &data)
void GdbEngine::rebuildModel()
{
PENDING_DEBUG("REBUILDING MODEL");
emit gdbInputAvailable(QString(),
_c('[') + currentTime() + _("] <Rebuild Watchmodel>"));
emit gdbInputAvailable(LogStatus, _("<Rebuild Watchmodel>"));
q->showStatusMessage(tr("Finished retrieving data."), 400);
qq->watchHandler()->endCycle();
......@@ -3171,7 +3171,7 @@ void GdbEngine::sendWatchParameters(const QByteArray &params0)
encoded[encoded.size() - 1] = '}';
params.replace('\0','!');
emit gdbInputAvailable(QString(), QString::fromUtf8(params));
emit gdbInputAvailable(LogMisc, QString::fromUtf8(params));
postCommand(_(encoded));
}
......
......@@ -81,8 +81,8 @@ public:
~GdbEngine();
signals:
void gdbInputAvailable(const QString &prefix, const QString &msg);
void gdbOutputAvailable(const QString &prefix, const QString &msg);
void gdbInputAvailable(int channel, const QString &msg);
void gdbOutputAvailable(int channel, const QString &msg);
void applicationOutputAvailable(const QString &output);
private:
......
......@@ -140,11 +140,11 @@ TcfEngine::TcfEngine(DebuggerManager *parent)
//connect(m_socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
// thism SLOT(socketStateChanged(QAbstractSocket::SocketState)));
connect(this, SIGNAL(tcfOutputAvailable(QString,QString)),
q, SLOT(showDebuggerOutput(QString,QString)),
connect(this, SIGNAL(tcfOutputAvailable(int,QString)),
q, SLOT(showDebuggerOutput(int,QString)),
Qt::QueuedConnection);
connect(this, SIGNAL(tcfInputAvailable(QString,QString)),
q, SLOT(showDebuggerInput(QString,QString)),
connect(this, SIGNAL(tcfInputAvailable(int,QString)),
q, SLOT(showDebuggerInput(int,QString)),
Qt::QueuedConnection);
connect(this, SIGNAL(applicationOutputAvailable(QString)),
q, SLOT(showApplicationOutput(QString)),
......@@ -347,7 +347,7 @@ void TcfEngine::handleResponse(const QByteArray &response)
int token = parts.at(1).toInt();
TcfCommand tcf = m_cookieForToken[token];
SDEBUG("COMMAND NOT RECOGNIZED FOR TOKEN" << token << tcf.toString());
emit tcfOutputAvailable("", QString::number(token) + "^"
emit tcfOutputAvailable(LogOutput, QString::number(token) + "^"
+ "NOT RECOQNIZED: " + quoteUnprintableLatin1(response));
acknowledgeResult();
} else if (n == 2 && tag == "F") { // flow control
......@@ -358,7 +358,7 @@ void TcfEngine::handleResponse(const QByteArray &response)
int token = parts.at(1).toInt();
QByteArray message = parts.at(2);
JsonValue data(parts.at(3));
emit tcfOutputAvailable("", QString("%1^%2%3").arg(token)
emit tcfOutputAvailable(LogOutput, QString("%1^%2%3").arg(token)
.arg(quoteUnprintableLatin1(response))
.arg(QString::fromUtf8(data.toString())));
TcfCommand tcf = m_cookieForToken[token];
......@@ -500,7 +500,7 @@ void TcfEngine::sendCommandNow(const TcfCommand &cmd)
int result = m_socket->write(cmd.command);
Q_UNUSED(result);
m_socket->flush();
emit tcfInputAvailable("send", QString::number(cmd.token) + " " + cmd.toString());
emit tcfInputAvailable(LogInput, QString::number(cmd.token) + " " + cmd.toString());
SDEBUG("SEND " << cmd.toString()); //<< " " << QString::number(result));
}
......
......@@ -68,8 +68,8 @@ public:
~TcfEngine();
signals:
void tcfInputAvailable(const QString &prefix, const QString &msg);
void tcfOutputAvailable(const QString &prefix, const QString &msg);
void tcfInputAvailable(int channel, const QString &msg);
void tcfOutputAvailable(int channel, const QString &msg);
void applicationOutputAvailable(const QString &output);
private:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment