diff options
Diffstat (limited to 'src/plugins/debugger/debuggeroutputwindow.cpp')
-rw-r--r-- | src/plugins/debugger/debuggeroutputwindow.cpp | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/plugins/debugger/debuggeroutputwindow.cpp b/src/plugins/debugger/debuggeroutputwindow.cpp new file mode 100644 index 0000000000..7f6bef85d7 --- /dev/null +++ b/src/plugins/debugger/debuggeroutputwindow.cpp @@ -0,0 +1,318 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception version +** 1.2, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ +#include "debuggeroutputwindow.h" + +#include <QtCore/QDebug> + +#include <QtGui/QAction> +#include <QtGui/QHBoxLayout> +#include <QtGui/QVBoxLayout> +#include <QtGui/QKeyEvent> +#include <QtGui/QLabel> +#include <QtGui/QLineEdit> +#include <QtGui/QMenu> +#include <QtGui/QSpacerItem> +#include <QtGui/QSplitter> +#include <QtGui/QTextBlock> + +#ifndef GDBDEBUGGERLEAN + +#include <aggregation/aggregate.h> +#include <find/basetextfind.h> + +using namespace Find; + +#endif // GDBDEBUGGERLEAN + +using Debugger::Internal::DebuggerOutputWindow; + +///////////////////////////////////////////////////////////////////// +// +// InputPane +// +///////////////////////////////////////////////////////////////////// + +class DebuggerPane : public QTextEdit +{ +public: + DebuggerPane(QWidget *parent) + : QTextEdit(parent) + { + m_clearContentsAction = new QAction(this); + m_clearContentsAction->setText("Clear contents"); + m_clearContentsAction->setEnabled(true); + m_clearContentsAction->setShortcut(Qt::ControlModifier + Qt::Key_R); + connect(m_clearContentsAction, SIGNAL(triggered(bool)), + parent, SLOT(clearContents())); + + m_saveContentsAction = new QAction(this); + m_saveContentsAction->setText("Save contents"); + m_saveContentsAction->setEnabled(true); + } + + void contextMenuEvent(QContextMenuEvent *ev) + { + QMenu *menu = createStandardContextMenu(); + menu->addAction(m_clearContentsAction); + //menu->addAction(m_saveContentsAction); + addContextActions(menu); + menu->exec(ev->globalPos()); + delete menu; + } + + virtual void addContextActions(QMenu *) {} + +public: + QAction *m_clearContentsAction; + QAction *m_saveContentsAction; +}; + +class InputPane : public DebuggerPane +{ + Q_OBJECT +public: + InputPane(QWidget *parent) : DebuggerPane(parent) + { + m_commandExecutionAction = new QAction(this); + m_commandExecutionAction->setText("Execute line"); + m_commandExecutionAction->setEnabled(true); + //m_commandExecutionAction->setShortcut + // (Qt::ControlModifier + Qt::Key_Return); + + connect(m_commandExecutionAction, SIGNAL(triggered(bool)), + this, SLOT(executeCommand())); + } + +signals: + void commandExecutionRequested(const QString &); + void clearContentsRequested(); + void statusMessageRequested(const QString &, int); + void commandSelected(int); + +private slots: + void executeCommand() + { + emit commandExecutionRequested(textCursor().block().text()); + } + +private: + void keyPressEvent(QKeyEvent *ev) + { + if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_Return) + emit commandExecutionRequested(textCursor().block().text()); + else if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_R) + emit clearContentsRequested(); + else + QTextEdit::keyPressEvent(ev); + } + + void mouseDoubleClickEvent(QMouseEvent *ev) + { + QString line = cursorForPosition(ev->pos()).block().text(); + int n = 0; + + // cut time string + if (line.size() > 18 && line.at(0) == '[') + line = line.mid(18); + //qDebug() << line; + + for (int i = 0; i != line.size(); ++i) { + QChar c = line.at(i); + if (!c.isDigit()) + break; + n = 10 * n + c.unicode() - '0'; + } + emit commandSelected(n); + } + + void addContextActions(QMenu *menu) + { + menu->addAction(m_commandExecutionAction); + } + + void focusInEvent(QFocusEvent *ev) + { + emit statusMessageRequested("Type Ctrl-<Return> to execute a line.", -1); + QTextEdit::focusInEvent(ev); + } + + void focusOutEvent(QFocusEvent *ev) + { + emit statusMessageRequested(QString(), -1); + QTextEdit::focusOutEvent(ev); + } + + QAction *m_commandExecutionAction; +}; + + +///////////////////////////////////////////////////////////////////// +// +// CombinedPane +// +///////////////////////////////////////////////////////////////////// + +class CombinedPane : public DebuggerPane +{ + Q_OBJECT +public: + CombinedPane(QWidget *parent) + : DebuggerPane(parent) + {} + +public slots: + void gotoResult(int i) + { + QString needle = QString::number(i) + '^'; + QString needle2 = "stdout:" + needle; + QTextCursor cursor(document()); + do { + const QString line = cursor.block().text(); + if (line.startsWith(needle) || line.startsWith(needle2)) { + setFocus(); + setTextCursor(cursor); + ensureCursorVisible(); + cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor); + setTextCursor(cursor); + break; + } + } while (cursor.movePosition(QTextCursor::Down)); + } +}; + + +///////////////////////////////////////////////////////////////////// +// +// DebuggerOutputWindow +// +///////////////////////////////////////////////////////////////////// + +DebuggerOutputWindow::DebuggerOutputWindow(QWidget *parent) + : QWidget(parent) +{ + setWindowTitle(tr("Gdb")); + + QSplitter *m_splitter = new QSplitter(Qt::Horizontal, this); + // mixed input/output + m_combinedText = new CombinedPane(this); + m_combinedText->setReadOnly(true); + m_combinedText->setReadOnly(false); + m_combinedText->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + + // input only + m_inputText = new InputPane(this); + m_inputText->setReadOnly(false); + m_inputText->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + + m_splitter->addWidget(m_inputText); + m_splitter->addWidget(m_combinedText); + + QGridLayout *layout = new QGridLayout(this); + layout->setMargin(0); + layout->addWidget(m_splitter); + setLayout(layout); + +#ifndef GDBDEBUGGERLEAN + Aggregation::Aggregate *aggregate = new Aggregation::Aggregate; + aggregate->add(m_combinedText); + aggregate->add(new BaseTextFind(m_combinedText)); + + aggregate = new Aggregation::Aggregate; + aggregate->add(m_inputText); + aggregate->add(new BaseTextFind(m_inputText)); +#endif + + connect(m_inputText, SIGNAL(commandExecutionRequested(QString)), + this, SIGNAL(commandExecutionRequested(QString))); + connect(m_inputText, SIGNAL(statusMessageRequested(QString,int)), + this, SIGNAL(statusMessageRequested(QString,int))); + connect(m_inputText, SIGNAL(commandSelected(int)), + m_combinedText, SLOT(gotoResult(int))); +}; + +void DebuggerOutputWindow::onReturnPressed() +{ + emit commandExecutionRequested(m_commandEdit->text()); +} + +void DebuggerOutputWindow::showOutput(const QString &prefix, const QString &output) +{ + if (output.isEmpty()) + return; + foreach (QString line, output.split("\n")) { + // FIXME: QTextEdit asserts on really long lines... + const int n = 3000; + if (line.size() > n) + line = line.left(n) + " [...] <cut off>"; + m_combinedText->append(prefix + line); + } + QTextCursor cursor = m_combinedText->textCursor(); + cursor.movePosition(QTextCursor::End); + m_combinedText->setTextCursor(cursor); + m_combinedText->ensureCursorVisible(); +} + +void DebuggerOutputWindow::showInput(const QString &prefix, const QString &input) +{ + m_inputText->append(input); + QTextCursor cursor = m_inputText->textCursor(); + cursor.movePosition(QTextCursor::End); + m_inputText->setTextCursor(cursor); + m_inputText->ensureCursorVisible(); + showOutput("input:", input); +} + +void DebuggerOutputWindow::clearContents() +{ + m_combinedText->clear(); + m_inputText->clear(); +} + +void DebuggerOutputWindow::setCursor(const QCursor &cursor) +{ + m_combinedText->setCursor(cursor); + m_inputText->setCursor(cursor); + QWidget::setCursor(cursor); +} + +QString DebuggerOutputWindow::combinedContents() const +{ + return m_combinedText->toPlainText(); +} + +QString DebuggerOutputWindow::inputContents() const +{ + return m_inputText->toPlainText(); +} + +#include "debuggeroutputwindow.moc" |