summaryrefslogtreecommitdiff
path: root/src/plugins/debugger/debuggeroutputwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/debugger/debuggeroutputwindow.cpp')
-rw-r--r--src/plugins/debugger/debuggeroutputwindow.cpp318
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"