diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 285d9b5bfc208cceefa8d0104b43cffdccba1549..4db85dcf01de7dd7f221b5bda68c7be8c18ba654 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -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); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 79225e61f89d8db99b4061e4f1812ad9f31ebe88..d466a78df3dd40b3adacc6a7090dbe40911be710 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -78,6 +78,7 @@ enum DebuggerActionCode UseAlternatingRowColors, AutoQuit, LockView, + LogTimeStamps, // Gdb GdbLocation, diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 1d8786af7cd6b0c7a44e44cb8e5ffe5219b32d66..fa8fc9ff3ac62170eee4a0c5a216eb8e5d26ee21 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -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); } diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index 1bdd14249ef35f34c899163a332c07993ad0acf0..9928fabeb3bcbbbbe0f88d598810517ca8f0a3b1 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -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(); diff --git a/src/plugins/debugger/debuggeroutputwindow.cpp b/src/plugins/debugger/debuggeroutputwindow.cpp index a953abc502a455117704835e0a00ec98b6b0617b..7596ebee3da75fd673d1beafd76b21636d4d5827 100644 --- a/src/plugins/debugger/debuggeroutputwindow.cpp +++ b/src/plugins/debugger/debuggeroutputwindow.cpp @@ -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() diff --git a/src/plugins/debugger/debuggeroutputwindow.h b/src/plugins/debugger/debuggeroutputwindow.h index 082ef5c0429e7ac294562445d5422aa8a7b33f6c..1f9c906818b4d365e2ef52b7d3683607dff85466 100644 --- a/src/plugins/debugger/debuggeroutputwindow.h +++ b/src/plugins/debugger/debuggeroutputwindow.h @@ -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(); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 0974b09c9b7d3b9471814345963044e34b49836c..04fd1d281d45d810524450102a591a143f2dcfd3 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -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 ¶ms0) encoded[encoded.size() - 1] = '}'; params.replace('\0','!'); - emit gdbInputAvailable(QString(), QString::fromUtf8(params)); + emit gdbInputAvailable(LogMisc, QString::fromUtf8(params)); postCommand(_(encoded)); } diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 77a4f5935779fd7e3abc92f4bc0a300a0cd4b413..6ec7818266f8c089c62ab3ed2220fdced55eb011 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -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: diff --git a/src/plugins/debugger/tcf/tcfengine.cpp b/src/plugins/debugger/tcf/tcfengine.cpp index 94585085d93195f151c91197997ac1cf7185d8ff..b699f40954a85de1f026ff7cc8984e9838ae2b8f 100644 --- a/src/plugins/debugger/tcf/tcfengine.cpp +++ b/src/plugins/debugger/tcf/tcfengine.cpp @@ -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)); } diff --git a/src/plugins/debugger/tcf/tcfengine.h b/src/plugins/debugger/tcf/tcfengine.h index b76ce123cf3b328ec73df458509585a5a28b3cd5..ff5844c436b119c8dd30cb78e27667d8ba3b0fb9 100644 --- a/src/plugins/debugger/tcf/tcfengine.h +++ b/src/plugins/debugger/tcf/tcfengine.h @@ -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: