forked from qt-creator/qt-creator
ScriptConsole: Use QTreeView
Use QTreeView instead of modified QPlainTextEdit to show the console. Using a QTreeView gives more control over output display as well as separates out the model from the view. Change-Id: I436b13ed042c00d09d6de627b442bfd8d10d2236 Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
This commit is contained in:
@@ -30,5 +30,11 @@
|
|||||||
<file>images/location_16.png</file>
|
<file>images/location_16.png</file>
|
||||||
<file>images/location_24.png</file>
|
<file>images/location_24.png</file>
|
||||||
<file>images/pin.xpm</file>
|
<file>images/pin.xpm</file>
|
||||||
|
<file>images/collapse.png</file>
|
||||||
|
<file>images/error.png</file>
|
||||||
|
<file>images/expand.png</file>
|
||||||
|
<file>images/log.png</file>
|
||||||
|
<file>images/prompt.png</file>
|
||||||
|
<file>images/warning.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
BIN
src/plugins/debugger/images/collapse.png
Normal file
BIN
src/plugins/debugger/images/collapse.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 986 B |
BIN
src/plugins/debugger/images/error.png
Normal file
BIN
src/plugins/debugger/images/error.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/plugins/debugger/images/expand.png
Normal file
BIN
src/plugins/debugger/images/expand.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 997 B |
BIN
src/plugins/debugger/images/log.png
Normal file
BIN
src/plugins/debugger/images/log.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/plugins/debugger/images/prompt.png
Normal file
BIN
src/plugins/debugger/images/prompt.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/plugins/debugger/images/warning.png
Normal file
BIN
src/plugins/debugger/images/warning.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
179
src/plugins/debugger/qml/consolebackend.cpp
Normal file
179
src/plugins/debugger/qml/consolebackend.cpp
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "consolebackend.h"
|
||||||
|
#include "qmlengine.h"
|
||||||
|
#include "qmladapter.h"
|
||||||
|
|
||||||
|
#include "debuggerstringutils.h"
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ConsoleBackend
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ConsoleBackend::ConsoleBackend(QObject *parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// QmlJSConsoleBackend
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
QmlJSConsoleBackend::QmlJSConsoleBackend(QObject *parent) :
|
||||||
|
ConsoleBackend(parent),
|
||||||
|
m_engine(0),
|
||||||
|
m_inferiorStopped(false),
|
||||||
|
m_isValidContext(false),
|
||||||
|
m_Error(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlJSConsoleBackend::setInferiorStopped(bool isInferiorStopped)
|
||||||
|
{
|
||||||
|
m_inferiorStopped = isInferiorStopped;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlJSConsoleBackend::inferiorStopped() const
|
||||||
|
{
|
||||||
|
return m_inferiorStopped;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlJSConsoleBackend::setEngine(QmlEngine *engine)
|
||||||
|
{
|
||||||
|
m_engine = engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlEngine *QmlJSConsoleBackend::engine() const
|
||||||
|
{
|
||||||
|
return m_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlJSConsoleBackend::setIsValidContext(bool isValidContext)
|
||||||
|
{
|
||||||
|
m_isValidContext = isValidContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlJSConsoleBackend::isValidContext() const
|
||||||
|
{
|
||||||
|
return m_isValidContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlJSConsoleBackend::onDebugQueryStateChanged(
|
||||||
|
QmlJsDebugClient::QDeclarativeDebugQuery::State state)
|
||||||
|
{
|
||||||
|
QmlJsDebugClient::QDeclarativeDebugExpressionQuery *query =
|
||||||
|
qobject_cast<QmlJsDebugClient::QDeclarativeDebugExpressionQuery *>(
|
||||||
|
sender());
|
||||||
|
if (query && state != QmlJsDebugClient::QDeclarativeDebugQuery::Error)
|
||||||
|
emit message(ConsoleItemModel::UndefinedType,
|
||||||
|
query->result().toString());
|
||||||
|
else
|
||||||
|
emit message(ConsoleItemModel::ErrorType,
|
||||||
|
_("Error evaluating expression."));
|
||||||
|
delete query;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlJSConsoleBackend::evaluate(const QString &script,
|
||||||
|
bool *returnKeyConsumed)
|
||||||
|
{
|
||||||
|
*returnKeyConsumed = true;
|
||||||
|
m_Error = false;
|
||||||
|
//Check if string is only white spaces
|
||||||
|
if (!script.trimmed().isEmpty()) {
|
||||||
|
//Check for a valid context
|
||||||
|
if (m_isValidContext) {
|
||||||
|
//check if it can be evaluated
|
||||||
|
if (canEvaluateScript(script)) {
|
||||||
|
//Evaluate expression based on engine state
|
||||||
|
//When engine->state() == InferiorStopOk, the expression
|
||||||
|
//is sent to V8DebugService. In all other cases, the
|
||||||
|
//expression is evaluated by QDeclarativeEngine.
|
||||||
|
if (!m_inferiorStopped) {
|
||||||
|
QmlAdapter *adapter = m_engine->adapter();
|
||||||
|
QTC_ASSERT(adapter, return);
|
||||||
|
QDeclarativeEngineDebug *engineDebug =
|
||||||
|
adapter->engineDebugClient();
|
||||||
|
|
||||||
|
int id = adapter->currentSelectedDebugId();
|
||||||
|
if (engineDebug && id != -1) {
|
||||||
|
QDeclarativeDebugExpressionQuery *query =
|
||||||
|
engineDebug->queryExpressionResult(id, script);
|
||||||
|
connect(query,
|
||||||
|
SIGNAL(stateChanged(
|
||||||
|
QmlJsDebugClient::QDeclarativeDebugQuery
|
||||||
|
::State)),
|
||||||
|
this,
|
||||||
|
SLOT(onDebugQueryStateChanged(
|
||||||
|
QmlJsDebugClient::QDeclarativeDebugQuery
|
||||||
|
::State)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emit evaluateExpression(script);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*returnKeyConsumed = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Incase of invalid context, append the expression to history
|
||||||
|
//and show Error message
|
||||||
|
m_Error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlJSConsoleBackend::emitErrorMessage()
|
||||||
|
{
|
||||||
|
if (m_Error)
|
||||||
|
emit message(
|
||||||
|
ConsoleItemModel::ErrorType,
|
||||||
|
_("Cannot evaluate without a valid QML/JS Context"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlJSConsoleBackend::canEvaluateScript(const QString &script)
|
||||||
|
{
|
||||||
|
m_interpreter.clearText();
|
||||||
|
m_interpreter.appendText(script);
|
||||||
|
return m_interpreter.canEvaluate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
100
src/plugins/debugger/qml/consolebackend.h
Normal file
100
src/plugins/debugger/qml/consolebackend.h
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CONSOLEBACKEND_H
|
||||||
|
#define CONSOLEBACKEND_H
|
||||||
|
|
||||||
|
#include "consoleitemmodel.h"
|
||||||
|
#include "interactiveinterpreter.h"
|
||||||
|
|
||||||
|
#include <qmljsdebugclient/qdeclarativeenginedebug.h>
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ConsoleBackend : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ConsoleBackend(QObject *parent = 0);
|
||||||
|
|
||||||
|
virtual void emitErrorMessage() = 0;
|
||||||
|
|
||||||
|
virtual void evaluate(const QString &, bool *returnKeyConsumed) = 0;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void message(ConsoleItemModel::ItemType itemType, const QString &msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
class QmlEngine;
|
||||||
|
class QmlJSConsoleBackend : public ConsoleBackend
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit QmlJSConsoleBackend(QObject *parent = 0);
|
||||||
|
|
||||||
|
void setInferiorStopped(bool inferiorStopped);
|
||||||
|
bool inferiorStopped() const;
|
||||||
|
|
||||||
|
void setEngine(QmlEngine *engine);
|
||||||
|
QmlEngine *engine() const;
|
||||||
|
|
||||||
|
void setIsValidContext(bool isValidContext);
|
||||||
|
bool isValidContext() const;
|
||||||
|
|
||||||
|
virtual void evaluate(const QString &, bool *returnKeyConsumed);
|
||||||
|
void emitErrorMessage();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onDebugQueryStateChanged(
|
||||||
|
QmlJsDebugClient::QDeclarativeDebugQuery::State state);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void evaluateExpression(const QString &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool canEvaluateScript(const QString &script);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QmlEngine *m_engine;
|
||||||
|
InteractiveInterpreter m_interpreter;
|
||||||
|
bool m_inferiorStopped;
|
||||||
|
bool m_isValidContext;
|
||||||
|
bool m_Error;
|
||||||
|
};
|
||||||
|
|
||||||
|
} //Internal
|
||||||
|
} //Debugger
|
||||||
|
|
||||||
|
#endif // CONSOLEBACKEND_H
|
||||||
278
src/plugins/debugger/qml/consoleeditor.cpp
Normal file
278
src/plugins/debugger/qml/consoleeditor.cpp
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "consoleeditor.h"
|
||||||
|
#include "consoleitemmodel.h"
|
||||||
|
#include "consoleitemdelegate.h"
|
||||||
|
#include "consolebackend.h"
|
||||||
|
|
||||||
|
#include "debuggerstringutils.h"
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <QtGui/QMenu>
|
||||||
|
#include <QtGui/QKeyEvent>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ConsoleEditor
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ConsoleEditor::ConsoleEditor(const QModelIndex &index,
|
||||||
|
ConsoleBackend *backend,
|
||||||
|
QWidget *parent) :
|
||||||
|
QTextEdit(parent),
|
||||||
|
m_consoleBackend(backend),
|
||||||
|
m_historyIndex(index),
|
||||||
|
m_prompt(QLatin1String(":/debugger/images/prompt.png")),
|
||||||
|
m_startOfEditableArea(0)
|
||||||
|
{
|
||||||
|
setFrameStyle(QFrame::NoFrame);
|
||||||
|
setUndoRedoEnabled(false);
|
||||||
|
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||||
|
document()->addResource(QTextDocument::ImageResource,
|
||||||
|
QUrl(QLatin1String("prompt")), m_prompt);
|
||||||
|
QTextImageFormat format;
|
||||||
|
format.setName(QLatin1String("prompt"));
|
||||||
|
format.setHeight(9);
|
||||||
|
format.setWidth(9);
|
||||||
|
textCursor().insertImage(format);
|
||||||
|
textCursor().insertText(QLatin1String(" "));
|
||||||
|
m_startOfEditableArea = textCursor().position();
|
||||||
|
|
||||||
|
ensureCursorVisible();
|
||||||
|
setTextInteractionFlags(Qt::TextEditorInteraction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleEditor::keyPressEvent(QKeyEvent *e)
|
||||||
|
{
|
||||||
|
bool keyConsumed = false;
|
||||||
|
|
||||||
|
switch (e->key()) {
|
||||||
|
case Qt::Key_Return:
|
||||||
|
case Qt::Key_Enter:
|
||||||
|
if (m_consoleBackend) {
|
||||||
|
m_consoleBackend->evaluate(getCurrentScript(), &keyConsumed);
|
||||||
|
if (keyConsumed) {
|
||||||
|
emit editingFinished();
|
||||||
|
emit appendEditableRow();
|
||||||
|
//emit error message if there is an error
|
||||||
|
m_consoleBackend->emitErrorMessage();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emit editingFinished();
|
||||||
|
emit appendEditableRow();
|
||||||
|
keyConsumed = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_Backspace:
|
||||||
|
if (textCursor().selectionStart() <= m_startOfEditableArea)
|
||||||
|
keyConsumed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_Delete:
|
||||||
|
if (textCursor().selectionStart() < m_startOfEditableArea)
|
||||||
|
keyConsumed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_Home:
|
||||||
|
{
|
||||||
|
QTextCursor c(textCursor());
|
||||||
|
c.setPosition(m_startOfEditableArea);
|
||||||
|
setTextCursor(c);
|
||||||
|
keyConsumed = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_Up:
|
||||||
|
handleUpKey();
|
||||||
|
keyConsumed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_Down:
|
||||||
|
handleDownKey();
|
||||||
|
keyConsumed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Ctrl+Left: Moves the cursor one word to the left.
|
||||||
|
// Left: Moves the cursor one character to the left.
|
||||||
|
case Qt::Key_Left:
|
||||||
|
if (textCursor().position() <= m_startOfEditableArea
|
||||||
|
|| e->modifiers() & Qt::ControlModifier) {
|
||||||
|
QTextCursor c(textCursor());
|
||||||
|
c.setPosition(m_startOfEditableArea);
|
||||||
|
setTextCursor(c);
|
||||||
|
keyConsumed = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Ctrl+Right: Moves the cursor one word to the right.
|
||||||
|
// Right: Moves the cursor one character to the right.
|
||||||
|
case Qt::Key_Right:
|
||||||
|
if ( !(e->modifiers() & Qt::ControlModifier)
|
||||||
|
&& textCursor().position() <= m_startOfEditableArea) {
|
||||||
|
QTextCursor c(textCursor());
|
||||||
|
c.setPosition(m_startOfEditableArea);
|
||||||
|
setTextCursor(c);
|
||||||
|
keyConsumed = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Ctrl+C, Ctrl+Insert: Allow to Copy the selected text to the clipboard.
|
||||||
|
case Qt::Key_C:
|
||||||
|
case Qt::Key_Insert:
|
||||||
|
if (textCursor().selectionStart() < m_startOfEditableArea &&
|
||||||
|
!(e->modifiers() & Qt::ControlModifier))
|
||||||
|
keyConsumed = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Disallow any other keys in the prompt area
|
||||||
|
if (textCursor().selectionStart() < m_startOfEditableArea)
|
||||||
|
keyConsumed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keyConsumed)
|
||||||
|
QTextEdit::keyPressEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleEditor::contextMenuEvent(QContextMenuEvent *event)
|
||||||
|
{
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
bool editable = cursor.position() > m_startOfEditableArea;
|
||||||
|
QMenu *menu = new QMenu();
|
||||||
|
QAction *a;
|
||||||
|
|
||||||
|
a = menu->addAction(tr("Cu&t"), this, SLOT(cut()));
|
||||||
|
a->setEnabled(cursor.hasSelection() && editable);
|
||||||
|
|
||||||
|
a = menu->addAction(tr("&Copy"), this, SLOT(copy()));
|
||||||
|
a->setEnabled(cursor.hasSelection());
|
||||||
|
|
||||||
|
a = menu->addAction(tr("&Paste"), this, SLOT(paste()));
|
||||||
|
a->setEnabled(canPaste() && editable);
|
||||||
|
|
||||||
|
menu->addSeparator();
|
||||||
|
a = menu->addAction(tr("Select &All"), this, SLOT(selectAll()));
|
||||||
|
a->setEnabled(!document()->isEmpty());
|
||||||
|
|
||||||
|
menu->addSeparator();
|
||||||
|
menu->addAction(tr("C&lear"), this, SLOT(clear()));
|
||||||
|
|
||||||
|
menu->exec(event->globalPos());
|
||||||
|
|
||||||
|
delete menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleEditor::focusOutEvent(QFocusEvent * /*e*/)
|
||||||
|
{
|
||||||
|
emit editingFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleEditor::handleUpKey()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_historyIndex.isValid(), return);
|
||||||
|
int currentRow = m_historyIndex.row();
|
||||||
|
const QAbstractItemModel *model = m_historyIndex.model();
|
||||||
|
if (currentRow == model->rowCount() - 1)
|
||||||
|
m_cachedScript = getCurrentScript();
|
||||||
|
|
||||||
|
while (currentRow) {
|
||||||
|
currentRow--;
|
||||||
|
if (model->hasIndex(currentRow, 0)) {
|
||||||
|
QModelIndex index = model->index(currentRow, 0);
|
||||||
|
if (ConsoleItemModel::InputType ==
|
||||||
|
(ConsoleItemModel::ItemType)model->data(
|
||||||
|
index, ConsoleItemModel::TypeRole).toInt()) {
|
||||||
|
m_historyIndex = index;
|
||||||
|
replaceCurrentScript(model->data(
|
||||||
|
index, Qt::DisplayRole).
|
||||||
|
toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleEditor::handleDownKey()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_historyIndex.isValid(), return);
|
||||||
|
int currentRow = m_historyIndex.row();
|
||||||
|
const QAbstractItemModel *model = m_historyIndex.model();
|
||||||
|
while (currentRow < model->rowCount() - 1) {
|
||||||
|
currentRow++;
|
||||||
|
if (model->hasIndex(currentRow, 0)) {
|
||||||
|
QModelIndex index = model->index(currentRow, 0);
|
||||||
|
if (ConsoleItemModel::InputType ==
|
||||||
|
(ConsoleItemModel::ItemType)model->data(
|
||||||
|
index, ConsoleItemModel::TypeRole).toInt()) {
|
||||||
|
m_historyIndex = index;
|
||||||
|
if (currentRow == model->rowCount() - 1)
|
||||||
|
replaceCurrentScript(m_cachedScript);
|
||||||
|
else
|
||||||
|
replaceCurrentScript(model->data(
|
||||||
|
index, Qt::DisplayRole).
|
||||||
|
toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ConsoleEditor::getCurrentScript() const
|
||||||
|
{
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
cursor.setPosition(m_startOfEditableArea);
|
||||||
|
cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
|
||||||
|
QString script = cursor.selectedText();
|
||||||
|
//remove WS
|
||||||
|
return script.trimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleEditor::replaceCurrentScript(const QString &script)
|
||||||
|
{
|
||||||
|
QTextCursor cursor = textCursor();
|
||||||
|
cursor.setPosition(m_startOfEditableArea);
|
||||||
|
cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
|
||||||
|
cursor.removeSelectedText();
|
||||||
|
cursor.insertText(script);
|
||||||
|
setTextCursor(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
} //Internal
|
||||||
|
} //Debugger
|
||||||
81
src/plugins/debugger/qml/consoleeditor.h
Normal file
81
src/plugins/debugger/qml/consoleeditor.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CONSOLEEDITOR_H
|
||||||
|
#define CONSOLEEDITOR_H
|
||||||
|
|
||||||
|
#include "consoleitemmodel.h"
|
||||||
|
|
||||||
|
#include <QtGui/QTextEdit>
|
||||||
|
#include <QtCore/QModelIndex>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ConsoleBackend;
|
||||||
|
class ConsoleEditor : public QTextEdit
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ConsoleEditor(const QModelIndex &index,
|
||||||
|
ConsoleBackend *backend = 0,
|
||||||
|
QWidget *parent = 0);
|
||||||
|
|
||||||
|
QString getCurrentScript() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void keyPressEvent(QKeyEvent *e);
|
||||||
|
void contextMenuEvent(QContextMenuEvent *event);
|
||||||
|
void focusOutEvent(QFocusEvent *e);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void editingFinished();
|
||||||
|
void appendEditableRow();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void handleUpKey();
|
||||||
|
void handleDownKey();
|
||||||
|
|
||||||
|
void replaceCurrentScript(const QString &script);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ConsoleBackend *m_consoleBackend;
|
||||||
|
QModelIndex m_historyIndex;
|
||||||
|
QString m_cachedScript;
|
||||||
|
QImage m_prompt;
|
||||||
|
int m_startOfEditableArea;
|
||||||
|
};
|
||||||
|
|
||||||
|
} //Internal
|
||||||
|
} //Debugger
|
||||||
|
|
||||||
|
#endif // CONSOLEEDITOR_H
|
||||||
321
src/plugins/debugger/qml/consoleitemdelegate.cpp
Normal file
321
src/plugins/debugger/qml/consoleitemdelegate.cpp
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "consoleitemdelegate.h"
|
||||||
|
#include "consoleeditor.h"
|
||||||
|
#include "qmlengine.h"
|
||||||
|
|
||||||
|
#include <QtGui/QPainter>
|
||||||
|
#include <QtGui/QTreeView>
|
||||||
|
|
||||||
|
const char CONSOLE_LOG_BACKGROUND_COLOR[] = "#2378B7";
|
||||||
|
const char CONSOLE_WARNING_BACKGROUND_COLOR[] = "#E6CD49";
|
||||||
|
const char CONSOLE_ERROR_BACKGROUND_COLOR[] = "#ED471A";
|
||||||
|
const char CONSOLE_EDITOR_BACKGROUND_COLOR[] = "#F7F7F7";
|
||||||
|
|
||||||
|
const char CONSOLE_LOG_TEXT_COLOR[] = "#333333";
|
||||||
|
const char CONSOLE_WARNING_TEXT_COLOR[] = "#666666";
|
||||||
|
const char CONSOLE_ERROR_TEXT_COLOR[] = "#1D5B93";
|
||||||
|
const char CONSOLE_EDITOR_TEXT_COLOR[] = "#000000";
|
||||||
|
|
||||||
|
const char CONSOLE_BORDER_COLOR[] = "#DEDEDE";
|
||||||
|
const float CONSOLE_ALPHA = 0.7f;
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ConsoleItemDelegate
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ConsoleItemDelegate::ConsoleItemDelegate(QObject *parent) :
|
||||||
|
QStyledItemDelegate(parent),
|
||||||
|
m_logIcon(QLatin1String(":/debugger/images/log.png")),
|
||||||
|
m_warningIcon(QLatin1String(":/debugger/images/warning.png")),
|
||||||
|
m_errorIcon(QLatin1String(":/debugger/images/error.png")),
|
||||||
|
m_expandIcon(QLatin1String(":/debugger/images/expand.png")),
|
||||||
|
m_collapseIcon(QLatin1String(":/debugger/images/collapse.png")),
|
||||||
|
m_prompt(QLatin1String(":/debugger/images/prompt.png")),
|
||||||
|
m_consoleBackend(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemDelegate::emitSizeHintChanged(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
emit sizeHintChanged(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemDelegate::setConsoleBackend(ConsoleBackend *consoleBackend)
|
||||||
|
{
|
||||||
|
m_consoleBackend = consoleBackend;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemDelegate::drawBackground(QPainter *painter, const QRect &rect,
|
||||||
|
ConsoleItemModel::ItemType itemType,
|
||||||
|
bool selected) const
|
||||||
|
{
|
||||||
|
QColor backgroundColor;
|
||||||
|
switch (itemType) {
|
||||||
|
case ConsoleItemModel::LogType:
|
||||||
|
backgroundColor = QColor(CONSOLE_LOG_BACKGROUND_COLOR);
|
||||||
|
break;
|
||||||
|
case ConsoleItemModel::WarningType:
|
||||||
|
backgroundColor = QColor(CONSOLE_WARNING_BACKGROUND_COLOR);
|
||||||
|
break;
|
||||||
|
case ConsoleItemModel::ErrorType:
|
||||||
|
backgroundColor = QColor(CONSOLE_ERROR_BACKGROUND_COLOR);
|
||||||
|
break;
|
||||||
|
case ConsoleItemModel::InputType:
|
||||||
|
backgroundColor = QColor(CONSOLE_EDITOR_BACKGROUND_COLOR);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
backgroundColor = QColor(CONSOLE_EDITOR_BACKGROUND_COLOR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (selected)
|
||||||
|
backgroundColor.setAlphaF(0.5f);
|
||||||
|
else
|
||||||
|
backgroundColor.setAlphaF(1 - CONSOLE_ALPHA);
|
||||||
|
|
||||||
|
painter->setBrush(backgroundColor);
|
||||||
|
|
||||||
|
painter->setPen(Qt::NoPen);
|
||||||
|
painter->drawRect(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QStyleOptionViewItemV4 opt = option;
|
||||||
|
initStyleOption(&opt, index);
|
||||||
|
painter->save();
|
||||||
|
|
||||||
|
//Set Colors
|
||||||
|
QColor textColor;
|
||||||
|
QIcon taskIcon;
|
||||||
|
ConsoleItemModel::ItemType type =
|
||||||
|
(ConsoleItemModel::ItemType)index.data(
|
||||||
|
ConsoleItemModel::TypeRole).toInt();
|
||||||
|
switch (type) {
|
||||||
|
case ConsoleItemModel::LogType:
|
||||||
|
textColor = QColor(CONSOLE_LOG_TEXT_COLOR);
|
||||||
|
taskIcon = m_logIcon;
|
||||||
|
break;
|
||||||
|
case ConsoleItemModel::WarningType:
|
||||||
|
textColor = QColor(CONSOLE_WARNING_TEXT_COLOR);
|
||||||
|
taskIcon = m_warningIcon;
|
||||||
|
break;
|
||||||
|
case ConsoleItemModel::ErrorType:
|
||||||
|
textColor = QColor(CONSOLE_ERROR_TEXT_COLOR);
|
||||||
|
taskIcon = m_errorIcon;
|
||||||
|
break;
|
||||||
|
case ConsoleItemModel::InputType:
|
||||||
|
textColor = QColor(CONSOLE_EDITOR_TEXT_COLOR);
|
||||||
|
taskIcon = m_prompt;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
textColor = QColor(CONSOLE_EDITOR_TEXT_COLOR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Paint background
|
||||||
|
drawBackground(painter, opt.rect, type,
|
||||||
|
bool(opt.state & QStyle::State_Selected));
|
||||||
|
|
||||||
|
//Calculate positions
|
||||||
|
const QTreeView *view = qobject_cast<const QTreeView *>(opt.widget);
|
||||||
|
int level = 0;
|
||||||
|
QModelIndex idx(index);
|
||||||
|
while (idx.parent() != QModelIndex()) {
|
||||||
|
idx = idx.parent();
|
||||||
|
level++;
|
||||||
|
}
|
||||||
|
int width = view->width() - level * view->indentation();
|
||||||
|
bool showTypeIcon = index.parent() == QModelIndex();
|
||||||
|
bool showExpandableIcon = type != ConsoleItemModel::InputType &&
|
||||||
|
type != ConsoleItemModel::UndefinedType;
|
||||||
|
|
||||||
|
QRect rect(opt.rect.x(), opt.rect.top(), width, opt.rect.height());
|
||||||
|
ConsoleItemPositions positions(rect, opt.font, showTypeIcon,
|
||||||
|
showExpandableIcon);
|
||||||
|
|
||||||
|
// Paint TaskIconArea:
|
||||||
|
if (showTypeIcon)
|
||||||
|
painter->drawPixmap(positions.adjustedLeft(), positions.adjustedTop(),
|
||||||
|
taskIcon.pixmap(positions.typeIconWidth(),
|
||||||
|
positions.typeIconHeight()));
|
||||||
|
|
||||||
|
// Set Text Color
|
||||||
|
painter->setPen(textColor);
|
||||||
|
// Paint TextArea:
|
||||||
|
// Layout the description
|
||||||
|
QTextLayout tl(index.data(Qt::DisplayRole).toString(), opt.font);
|
||||||
|
layoutText(tl, positions.textAreaWidth());
|
||||||
|
tl.draw(painter, QPoint(positions.textAreaLeft(), positions.adjustedTop()));
|
||||||
|
|
||||||
|
//skip if area is editable
|
||||||
|
if (showExpandableIcon) {
|
||||||
|
// Paint ExpandableIconArea:
|
||||||
|
QIcon expandCollapseIcon;
|
||||||
|
if (index.model()->rowCount(index)) {
|
||||||
|
if (view->isExpanded(index))
|
||||||
|
expandCollapseIcon = m_collapseIcon;
|
||||||
|
else
|
||||||
|
expandCollapseIcon = m_expandIcon;
|
||||||
|
}
|
||||||
|
painter->drawPixmap(positions.expandCollapseIconLeft(),
|
||||||
|
positions.adjustedTop(),
|
||||||
|
expandCollapseIcon.pixmap(
|
||||||
|
positions.expandCollapseIconWidth(),
|
||||||
|
positions.expandCollapseIconHeight()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator lines
|
||||||
|
painter->setPen(QColor(CONSOLE_BORDER_COLOR));
|
||||||
|
if (!index.flags() & Qt::ItemIsEditable)
|
||||||
|
painter->drawLine(0, opt.rect.bottom(), opt.rect.right(),
|
||||||
|
opt.rect.bottom());
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize ConsoleItemDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QStyleOptionViewItemV4 opt = option;
|
||||||
|
initStyleOption(&opt, index);
|
||||||
|
|
||||||
|
const QTreeView *view = qobject_cast<const QTreeView *>(opt.widget);
|
||||||
|
int level = 0;
|
||||||
|
QModelIndex idx(index);
|
||||||
|
while (idx.parent() != QModelIndex()) {
|
||||||
|
idx = idx.parent();
|
||||||
|
level++;
|
||||||
|
}
|
||||||
|
int width = view->width() - level * view->indentation();
|
||||||
|
if (index.flags() & Qt::ItemIsEditable)
|
||||||
|
return QSize(width, view->height() * 1/2);
|
||||||
|
|
||||||
|
ConsoleItemModel::ItemType type =
|
||||||
|
(ConsoleItemModel::ItemType)index.data(
|
||||||
|
ConsoleItemModel::TypeRole).toInt();
|
||||||
|
bool showTypeIcon = index.parent() == QModelIndex();
|
||||||
|
bool showExpandableIcon = type != ConsoleItemModel::InputType &&
|
||||||
|
type != ConsoleItemModel::UndefinedType;
|
||||||
|
|
||||||
|
QRect rect(level * view->indentation(), 0, width, 0);
|
||||||
|
ConsoleItemPositions positions(rect, opt.font,
|
||||||
|
showTypeIcon,
|
||||||
|
showExpandableIcon);
|
||||||
|
|
||||||
|
QTextLayout tl(index.data(Qt::DisplayRole).toString(), option.font);
|
||||||
|
qreal height = layoutText(tl, positions.textAreaWidth());
|
||||||
|
height += 2 * ConsoleItemPositions::ITEM_PADDING;
|
||||||
|
if (height < positions.minimumHeight())
|
||||||
|
height = positions.minimumHeight();
|
||||||
|
|
||||||
|
return QSize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *ConsoleItemDelegate::createEditor(QWidget *parent,
|
||||||
|
const QStyleOptionViewItem &/*option*/,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
|
||||||
|
{
|
||||||
|
ConsoleEditor *editor = new ConsoleEditor(index, m_consoleBackend, parent);
|
||||||
|
connect(editor, SIGNAL(appendEditableRow()),
|
||||||
|
this, SIGNAL(appendEditableRow()));
|
||||||
|
connect(editor, SIGNAL(editingFinished()),
|
||||||
|
this, SLOT(commitAndCloseEditor()));
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemDelegate::setEditorData(QWidget *editor,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
ConsoleEditor *edtr = qobject_cast<ConsoleEditor *>(editor);
|
||||||
|
edtr->insertPlainText(index.data(Qt::DisplayRole).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemDelegate::setModelData(QWidget *editor,
|
||||||
|
QAbstractItemModel *model,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
ConsoleEditor *edtr = qobject_cast<ConsoleEditor *>(editor);
|
||||||
|
model->setData(index, edtr->getCurrentScript(), Qt::DisplayRole);
|
||||||
|
model->setData(index, edtr->getCurrentScript(), ConsoleItemModel::TypeRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemDelegate::updateEditorGeometry(QWidget *editor,
|
||||||
|
const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &/*index*/) const
|
||||||
|
{
|
||||||
|
QStyleOptionViewItemV4 opt = option;
|
||||||
|
editor->setGeometry(QRect(opt.rect.x(), opt.rect.top(),
|
||||||
|
opt.rect.width(), opt.rect.bottom()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemDelegate::currentChanged(const QModelIndex ¤t,
|
||||||
|
const QModelIndex &previous)
|
||||||
|
{
|
||||||
|
emit sizeHintChanged(current);
|
||||||
|
emit sizeHintChanged(previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemDelegate::commitAndCloseEditor()
|
||||||
|
{
|
||||||
|
ConsoleEditor *editor = qobject_cast<ConsoleEditor *>(sender());
|
||||||
|
emit commitData(editor);
|
||||||
|
emit closeEditor(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ConsoleItemDelegate::layoutText(QTextLayout &tl, int width) const
|
||||||
|
{
|
||||||
|
qreal height = 0;
|
||||||
|
tl.beginLayout();
|
||||||
|
while (true) {
|
||||||
|
QTextLine line = tl.createLine();
|
||||||
|
|
||||||
|
if (!line.isValid())
|
||||||
|
break;
|
||||||
|
line.setLeadingIncluded(true);
|
||||||
|
line.setLineWidth(width);
|
||||||
|
line.setPosition(QPoint(0, height));
|
||||||
|
height += line.height();
|
||||||
|
}
|
||||||
|
tl.endLayout();
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //Internal
|
||||||
|
} //Debugger
|
||||||
174
src/plugins/debugger/qml/consoleitemdelegate.h
Normal file
174
src/plugins/debugger/qml/consoleitemdelegate.h
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CONSOLEITEMDELEGATE_H
|
||||||
|
#define CONSOLEITEMDELEGATE_H
|
||||||
|
|
||||||
|
#include "consoleitemmodel.h"
|
||||||
|
|
||||||
|
#include <QTextLayout>
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ConsoleBackend;
|
||||||
|
class ConsoleItemDelegate : public QStyledItemDelegate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ConsoleItemDelegate(QObject *parent = 0);
|
||||||
|
void emitSizeHintChanged(const QModelIndex &index);
|
||||||
|
void setConsoleBackend(ConsoleBackend *consoleBackend);
|
||||||
|
|
||||||
|
void drawBackground(QPainter *painter, const QRect &rect,
|
||||||
|
ConsoleItemModel::ItemType itemType, bool selected) const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const;
|
||||||
|
QSize sizeHint(const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const;
|
||||||
|
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const;
|
||||||
|
void setEditorData(QWidget *editor, const QModelIndex &index) const;
|
||||||
|
void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||||
|
const QModelIndex &index) const;
|
||||||
|
|
||||||
|
void updateEditorGeometry(QWidget *editor,
|
||||||
|
const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void appendEditableRow();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void commitAndCloseEditor();
|
||||||
|
|
||||||
|
private:
|
||||||
|
qreal layoutText(QTextLayout &tl, int width) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QIcon m_logIcon;
|
||||||
|
const QIcon m_warningIcon;
|
||||||
|
const QIcon m_errorIcon;
|
||||||
|
const QIcon m_expandIcon;
|
||||||
|
const QIcon m_collapseIcon;
|
||||||
|
const QIcon m_prompt;
|
||||||
|
ConsoleBackend *m_consoleBackend;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------------+
|
||||||
|
| TYPEICONAREA EXPANDABLEICONAREA TEXTAREA |
|
||||||
|
+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------------+
|
||||||
|
| PROMPTAREA EDITABLEAREA |
|
||||||
|
+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
*/
|
||||||
|
class ConsoleItemPositions
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConsoleItemPositions(const QRect &rect,
|
||||||
|
const QFont &font = QFont(),
|
||||||
|
bool showTaskIconArea = true,
|
||||||
|
bool showExpandableIconArea = true)
|
||||||
|
: m_x(rect.x()),
|
||||||
|
m_width(rect.width()),
|
||||||
|
m_top(rect.top()),
|
||||||
|
m_bottom(rect.bottom()),
|
||||||
|
m_showTaskIconArea(showTaskIconArea),
|
||||||
|
m_showExpandableIconArea(showExpandableIconArea)
|
||||||
|
{
|
||||||
|
m_fontHeight = QFontMetrics(font).height();
|
||||||
|
}
|
||||||
|
|
||||||
|
int adjustedTop() const { return m_top + ITEM_PADDING; }
|
||||||
|
int adjustedLeft() const { return m_x + ITEM_PADDING; }
|
||||||
|
int adjustedRight() const { return m_width - ITEM_PADDING; }
|
||||||
|
int adjustedBottom() const { return m_bottom; }
|
||||||
|
int lineHeight() const { return m_fontHeight + 1; }
|
||||||
|
int minimumHeight() const { return typeIconHeight() + 2 * ITEM_PADDING; }
|
||||||
|
|
||||||
|
//PROMPTAREA is same as TYPEICONAREA
|
||||||
|
int typeIconLeft() const { return adjustedLeft(); }
|
||||||
|
int typeIconWidth() const { return TASK_ICON_SIZE; }
|
||||||
|
int typeIconHeight() const { return TASK_ICON_SIZE; }
|
||||||
|
int typeIconRight() const { return m_showTaskIconArea ?
|
||||||
|
typeIconLeft() + typeIconWidth() : adjustedLeft(); }
|
||||||
|
QRect typeIcon() const { return
|
||||||
|
QRect(typeIconLeft(), adjustedTop(),
|
||||||
|
typeIconWidth(), typeIconHeight()); }
|
||||||
|
|
||||||
|
int expandCollapseIconLeft() const { return typeIconRight() +
|
||||||
|
ITEM_SPACING; }
|
||||||
|
int expandCollapseIconWidth() const { return TASK_ICON_SIZE; }
|
||||||
|
int expandCollapseIconHeight() const { return TASK_ICON_SIZE; }
|
||||||
|
int expandCollapseIconRight() const { return m_showExpandableIconArea ?
|
||||||
|
expandCollapseIconLeft() + expandCollapseIconWidth() :
|
||||||
|
typeIconRight(); }
|
||||||
|
QRect expandCollapseIcon() const { return
|
||||||
|
QRect(expandCollapseIconLeft(), adjustedTop(),
|
||||||
|
expandCollapseIconWidth(), expandCollapseIconHeight()); }
|
||||||
|
|
||||||
|
int textAreaLeft() const { return expandCollapseIconRight() + ITEM_SPACING; }
|
||||||
|
int textAreaWidth() const { return textAreaRight() - textAreaLeft(); }
|
||||||
|
int textAreaRight() const { return adjustedRight() - ITEM_SPACING; }
|
||||||
|
QRect textArea() const { return
|
||||||
|
QRect(textAreaLeft(), adjustedTop(), textAreaWidth(), lineHeight()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_x;
|
||||||
|
int m_width;
|
||||||
|
int m_top;
|
||||||
|
int m_bottom;
|
||||||
|
int m_fontHeight;
|
||||||
|
bool m_showTaskIconArea;
|
||||||
|
bool m_showExpandableIconArea;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const int TASK_ICON_SIZE = 16;
|
||||||
|
static const int ITEM_PADDING = 2;
|
||||||
|
static const int ITEM_SPACING = 2 * ITEM_PADDING;
|
||||||
|
|
||||||
|
};
|
||||||
|
} //Internal
|
||||||
|
} //Debugger
|
||||||
|
|
||||||
|
#endif // CONSOLEITEMDELEGATE_H
|
||||||
348
src/plugins/debugger/qml/consoleitemmodel.cpp
Normal file
348
src/plugins/debugger/qml/consoleitemmodel.cpp
Normal file
@@ -0,0 +1,348 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "consoleitemmodel.h"
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ConsoleItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConsoleItem(const QString &data = QString(),
|
||||||
|
ConsoleItemModel::ItemType type = ConsoleItemModel::UndefinedType,
|
||||||
|
ConsoleItem *parent = 0);
|
||||||
|
~ConsoleItem();
|
||||||
|
|
||||||
|
ConsoleItem *child(int number);
|
||||||
|
int childCount() const;
|
||||||
|
QString text() const;
|
||||||
|
ConsoleItemModel::ItemType itemType() const;
|
||||||
|
bool insertChildren(int position, int count);
|
||||||
|
ConsoleItem *parent();
|
||||||
|
bool removeChildren(int position, int count);
|
||||||
|
bool removeColumns(int position, int columns);
|
||||||
|
int childNumber() const;
|
||||||
|
bool setData(const QString &text, ConsoleItemModel::ItemType itemType);
|
||||||
|
bool setText(const QString &text);
|
||||||
|
bool setItemType(ConsoleItemModel::ItemType itemType);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<ConsoleItem *> m_childItems;
|
||||||
|
QString m_text;
|
||||||
|
ConsoleItemModel::ItemType m_itemType;
|
||||||
|
ConsoleItem *m_parentItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ConsoleItem
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ConsoleItem::ConsoleItem(const QString &text,
|
||||||
|
ConsoleItemModel::ItemType itemType,
|
||||||
|
ConsoleItem *parent)
|
||||||
|
: m_text(text),
|
||||||
|
m_itemType(itemType),
|
||||||
|
m_parentItem(parent)
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleItem::~ConsoleItem()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_childItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleItem *ConsoleItem::child(int number)
|
||||||
|
{
|
||||||
|
return m_childItems.value(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConsoleItem::childCount() const
|
||||||
|
{
|
||||||
|
return m_childItems.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConsoleItem::childNumber() const
|
||||||
|
{
|
||||||
|
if (m_parentItem)
|
||||||
|
return m_parentItem->m_childItems.indexOf(const_cast<ConsoleItem *>(this));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ConsoleItem::text() const
|
||||||
|
{
|
||||||
|
return m_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleItemModel::ItemType ConsoleItem::itemType() const
|
||||||
|
{
|
||||||
|
return m_itemType;
|
||||||
|
}
|
||||||
|
\
|
||||||
|
bool ConsoleItem::insertChildren(int position, int count)
|
||||||
|
{
|
||||||
|
if (position < 0 || position > m_childItems.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int row = 0; row < count; ++row) {
|
||||||
|
ConsoleItem *item = new ConsoleItem(QString(),
|
||||||
|
ConsoleItemModel::UndefinedType, this);
|
||||||
|
m_childItems.insert(position, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleItem *ConsoleItem::parent()
|
||||||
|
{
|
||||||
|
return m_parentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleItem::removeChildren(int position, int count)
|
||||||
|
{
|
||||||
|
if (position < 0 || position + count > m_childItems.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int row = 0; row < count; ++row)
|
||||||
|
delete m_childItems.takeAt(position);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleItem::removeColumns(int /*position*/, int /*columns*/)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleItem::setData(const QString &text,
|
||||||
|
ConsoleItemModel::ItemType itemType)
|
||||||
|
{
|
||||||
|
m_text = text;
|
||||||
|
m_itemType = itemType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleItem::setText(const QString &text)
|
||||||
|
{
|
||||||
|
m_text = text;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleItem::setItemType(ConsoleItemModel::ItemType itemType)
|
||||||
|
{
|
||||||
|
m_itemType = itemType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ConsoleItemModel
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ConsoleItemModel::ConsoleItemModel(QObject *parent) :
|
||||||
|
QAbstractItemModel(parent)
|
||||||
|
{
|
||||||
|
m_rootItem = new ConsoleItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleItemModel::~ConsoleItemModel()
|
||||||
|
{
|
||||||
|
delete m_rootItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemModel::clear()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
reset();
|
||||||
|
delete m_rootItem;
|
||||||
|
m_rootItem = new ConsoleItem();
|
||||||
|
endResetModel();
|
||||||
|
|
||||||
|
//Insert an empty row
|
||||||
|
appendEditableRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemModel::appendItem(ItemType itemType, QString message)
|
||||||
|
{
|
||||||
|
int position = m_rootItem->childCount() - 1;
|
||||||
|
insertRow(position);
|
||||||
|
QModelIndex idx = index(position, 0);
|
||||||
|
if (getItem(idx)->setData(message, itemType))
|
||||||
|
emit dataChanged(idx, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleItemModel::appendEditableRow()
|
||||||
|
{
|
||||||
|
int position = m_rootItem->childCount();
|
||||||
|
insertRow(position);
|
||||||
|
QModelIndex idx = index(position, 0);
|
||||||
|
if (getItem(idx)->setData(QString(), ConsoleItemModel::InputType)) {
|
||||||
|
QModelIndex idx = index(position, 0);
|
||||||
|
emit dataChanged(idx, idx);
|
||||||
|
emit editableRowAppended(idx, QItemSelectionModel::ClearAndSelect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ConsoleEditor
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
QVariant ConsoleItemModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
ConsoleItem *item = getItem(index);
|
||||||
|
|
||||||
|
if (role == Qt::DisplayRole )
|
||||||
|
return item->text();
|
||||||
|
else if (role == ConsoleItemModel::TypeRole)
|
||||||
|
return int(item->itemType());
|
||||||
|
else
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex ConsoleItemModel::index(int row, int column,
|
||||||
|
const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (parent.isValid() && parent.column() != 0)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
if (column > 0)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
ConsoleItem *parentItem = getItem(parent);
|
||||||
|
|
||||||
|
ConsoleItem *childItem = parentItem->child(row);
|
||||||
|
if (childItem)
|
||||||
|
return createIndex(row, column, childItem);
|
||||||
|
else
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex ConsoleItemModel::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
ConsoleItem *childItem = getItem(index);
|
||||||
|
ConsoleItem *parentItem = childItem->parent();
|
||||||
|
|
||||||
|
if (parentItem == m_rootItem)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return createIndex(parentItem->childNumber(), 0, parentItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConsoleItemModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
ConsoleItem *parentItem = getItem(parent);
|
||||||
|
|
||||||
|
return parentItem->childCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConsoleItemModel::columnCount(const QModelIndex & /* parent */) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags ConsoleItemModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ConsoleItem *item = getItem(index);
|
||||||
|
if (item->parent() == m_rootItem && index.row() == m_rootItem->childCount() - 1)
|
||||||
|
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||||
|
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleItemModel::setData(const QModelIndex &index, const QVariant &value,
|
||||||
|
int role)
|
||||||
|
{
|
||||||
|
ConsoleItem *item = getItem(index);
|
||||||
|
bool result = false;
|
||||||
|
if (role == Qt::DisplayRole )
|
||||||
|
result = item->setText(value.toString());
|
||||||
|
else if (role == ConsoleItemModel::TypeRole)
|
||||||
|
result = item->setItemType((ItemType)value.toInt());
|
||||||
|
else if (value.canConvert(QVariant::String))
|
||||||
|
result = item->setText(value.toString());
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
emit dataChanged(index, index);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleItemModel::insertRows(int position, int rows, const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
ConsoleItem *parentItem = getItem(parent);
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
beginInsertRows(parent, position, position + rows - 1);
|
||||||
|
success = parentItem->insertChildren(position, rows);
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleItemModel::removeRows(int position, int rows, const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
ConsoleItem *parentItem = getItem(parent);
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
beginRemoveRows(parent, position, position + rows - 1);
|
||||||
|
success = parentItem->removeChildren(position, rows);
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleItem *ConsoleItemModel::getItem(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (index.isValid()) {
|
||||||
|
ConsoleItem *item = static_cast<ConsoleItem*>(index.internalPointer());
|
||||||
|
if (item) return item;
|
||||||
|
}
|
||||||
|
return m_rootItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //Internal
|
||||||
|
} //Debugger
|
||||||
94
src/plugins/debugger/qml/consoleitemmodel.h
Normal file
94
src/plugins/debugger/qml/consoleitemmodel.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CONSOLEITEMMODEL_H
|
||||||
|
#define CONSOLEITEMMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QtGui/QItemSelectionModel>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ConsoleItem;
|
||||||
|
class ConsoleItemModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum ItemType { InputType, LogType, WarningType, ErrorType,
|
||||||
|
UndefinedType //Can be used for unknown and for Return values
|
||||||
|
};
|
||||||
|
enum Roles { TypeRole = Qt::UserRole };
|
||||||
|
|
||||||
|
explicit ConsoleItemModel(QObject *parent = 0);
|
||||||
|
~ConsoleItemModel();
|
||||||
|
|
||||||
|
void appendItem(ItemType,QString);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void clear();
|
||||||
|
void appendEditableRow();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void editableRowAppended(const QModelIndex &index,
|
||||||
|
QItemSelectionModel::SelectionFlags flags);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
|
QModelIndex index(int row, int column,
|
||||||
|
const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
QModelIndex parent(const QModelIndex &index) const;
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value,
|
||||||
|
int role = Qt::EditRole);
|
||||||
|
|
||||||
|
bool insertRows(int position, int rows,
|
||||||
|
const QModelIndex &parent = QModelIndex());
|
||||||
|
bool removeRows(int position, int rows,
|
||||||
|
const QModelIndex &parent = QModelIndex());
|
||||||
|
|
||||||
|
ConsoleItem *getItem(const QModelIndex &index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ConsoleItem *m_rootItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
} //Internal
|
||||||
|
} //Debugger
|
||||||
|
|
||||||
|
#endif // CONSOLEITEMMODEL_H
|
||||||
157
src/plugins/debugger/qml/consoletreeview.cpp
Normal file
157
src/plugins/debugger/qml/consoletreeview.cpp
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "consoletreeview.h"
|
||||||
|
#include "consoleitemdelegate.h"
|
||||||
|
#include "consoleitemmodel.h"
|
||||||
|
#include "debuggerinternalconstants.h"
|
||||||
|
|
||||||
|
#include <QtGui/QMouseEvent>
|
||||||
|
#include <QtGui/QProxyStyle>
|
||||||
|
#include <QtGui/QPainter>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ConsoleTreeViewStyle : public QProxyStyle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void drawPrimitive(PrimitiveElement element,
|
||||||
|
const QStyleOption *option,
|
||||||
|
QPainter *painter,
|
||||||
|
const QWidget *widget = 0) const
|
||||||
|
{
|
||||||
|
if (element != QStyle::PE_PanelItemViewRow)
|
||||||
|
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
int styleHint(StyleHint hint, const QStyleOption *option = 0,
|
||||||
|
const QWidget *widget = 0,
|
||||||
|
QStyleHintReturn *returnData = 0) const {
|
||||||
|
if (hint == SH_ItemView_ShowDecorationSelected)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return QProxyStyle::styleHint(hint, option, widget, returnData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ConsoleTreeView
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ConsoleTreeView::ConsoleTreeView(QWidget *parent) :
|
||||||
|
QTreeView(parent)
|
||||||
|
{
|
||||||
|
setFrameStyle(QFrame::NoFrame);
|
||||||
|
setHeaderHidden(true);
|
||||||
|
setRootIsDecorated(false);
|
||||||
|
setEditTriggers(QAbstractItemView::AllEditTriggers);
|
||||||
|
setStyleSheet(QLatin1String("QTreeView::branch:has-siblings:!adjoins-item {"
|
||||||
|
"border-image: none;"
|
||||||
|
"image: none; }"
|
||||||
|
"QTreeView::branch:has-siblings:adjoins-item {"
|
||||||
|
"border-image: none;"
|
||||||
|
"image: none; }"
|
||||||
|
"QTreeView::branch:!has-children:!has-siblings:adjoins-item {"
|
||||||
|
"border-image: none;"
|
||||||
|
"image: none; }"
|
||||||
|
"QTreeView::branch:has-children:!has-siblings:closed,"
|
||||||
|
"QTreeView::branch:closed:has-children:has-siblings {"
|
||||||
|
"border-image: none;"
|
||||||
|
"image: none; }"
|
||||||
|
"QTreeView::branch:open:has-children:!has-siblings,"
|
||||||
|
"QTreeView::branch:open:has-children:has-siblings {"
|
||||||
|
"border-image: none;"
|
||||||
|
"image: none; }"));
|
||||||
|
ConsoleTreeViewStyle *style = new ConsoleTreeViewStyle;
|
||||||
|
setStyle(style);
|
||||||
|
style->setParent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleTreeView::setItemDelegate(QAbstractItemDelegate *delegate)
|
||||||
|
{
|
||||||
|
connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
||||||
|
delegate, SLOT(currentChanged(QModelIndex,QModelIndex)));
|
||||||
|
QTreeView::setItemDelegate(delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleTreeView::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
QPoint pos = event->pos();
|
||||||
|
QModelIndex index = indexAt(pos);
|
||||||
|
if (index.isValid()) {
|
||||||
|
ConsoleItemModel::ItemType type =
|
||||||
|
(ConsoleItemModel::ItemType)index.data(
|
||||||
|
ConsoleItemModel::TypeRole).toInt();
|
||||||
|
bool showTypeIcon = index.parent() == QModelIndex();
|
||||||
|
bool showExpandableIcon = type != ConsoleItemModel::InputType &&
|
||||||
|
type != ConsoleItemModel::UndefinedType;
|
||||||
|
ConsoleItemPositions positions(visualRect(index), viewOptions().font,
|
||||||
|
showTypeIcon, showExpandableIcon);
|
||||||
|
|
||||||
|
if (positions.expandCollapseIcon().contains(pos)) {
|
||||||
|
if (isExpanded(index))
|
||||||
|
setExpanded(index, false);
|
||||||
|
else
|
||||||
|
setExpanded(index, true);
|
||||||
|
} else {
|
||||||
|
QTreeView::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selectionModel()->setCurrentIndex(model()->index(
|
||||||
|
model()->rowCount() - 1, 0),
|
||||||
|
QItemSelectionModel::ClearAndSelect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleTreeView::resizeEvent(QResizeEvent *e)
|
||||||
|
{
|
||||||
|
static_cast<ConsoleItemDelegate *>(itemDelegate())->emitSizeHintChanged(
|
||||||
|
selectionModel()->currentIndex());
|
||||||
|
QTreeView::resizeEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleTreeView::drawBranches(QPainter *painter, const QRect &rect,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
ConsoleItemModel::ItemType type =
|
||||||
|
(ConsoleItemModel::ItemType)index.data(
|
||||||
|
ConsoleItemModel::TypeRole).toInt();
|
||||||
|
static_cast<ConsoleItemDelegate *>(itemDelegate())->drawBackground(
|
||||||
|
painter, rect, type, true);
|
||||||
|
QTreeView::drawBranches(painter, rect, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
} //Internal
|
||||||
|
} //Debugger
|
||||||
59
src/plugins/debugger/qml/consoletreeview.h
Normal file
59
src/plugins/debugger/qml/consoletreeview.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
||||||
|
** Please review the following information to ensure the GNU Lesser General
|
||||||
|
** Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** If you have questions regarding the use of this file, please contact
|
||||||
|
** Nokia at qt-info@nokia.com.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CONSOLETREEVIEW_H
|
||||||
|
#define CONSOLETREEVIEW_H
|
||||||
|
|
||||||
|
#include <QtGui/QTreeView>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ConsoleTreeView : public QTreeView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ConsoleTreeView(QWidget *parent = 0);
|
||||||
|
|
||||||
|
void setItemDelegate(QAbstractItemDelegate *delegate);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QMouseEvent *event);
|
||||||
|
void resizeEvent(QResizeEvent *e);
|
||||||
|
void drawBranches(QPainter *painter, const QRect &rect,
|
||||||
|
const QModelIndex &index) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} //Internal
|
||||||
|
} //Debugger
|
||||||
|
|
||||||
|
#endif // CONSOLETREEVIEW_H
|
||||||
@@ -10,7 +10,12 @@ HEADERS += \
|
|||||||
$$PWD/qscriptdebuggerclient.h \
|
$$PWD/qscriptdebuggerclient.h \
|
||||||
$$PWD/qmlv8debuggerclient.h \
|
$$PWD/qmlv8debuggerclient.h \
|
||||||
$$PWD/interactiveinterpreter.h \
|
$$PWD/interactiveinterpreter.h \
|
||||||
$$PWD/qmlv8debuggerclientconstants.h
|
$$PWD/qmlv8debuggerclientconstants.h \
|
||||||
|
$$PWD/consoletreeview.h \
|
||||||
|
$$PWD/consoleitemmodel.h \
|
||||||
|
$$PWD/consoleitemdelegate.h \
|
||||||
|
$$PWD/consoleeditor.h \
|
||||||
|
$$PWD/consolebackend.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/qmlengine.cpp \
|
$$PWD/qmlengine.cpp \
|
||||||
@@ -20,5 +25,10 @@ SOURCES += \
|
|||||||
$$PWD/qmljsscriptconsole.cpp \
|
$$PWD/qmljsscriptconsole.cpp \
|
||||||
$$PWD/qscriptdebuggerclient.cpp \
|
$$PWD/qscriptdebuggerclient.cpp \
|
||||||
$$PWD/qmlv8debuggerclient.cpp \
|
$$PWD/qmlv8debuggerclient.cpp \
|
||||||
$$PWD/interactiveinterpreter.cpp
|
$$PWD/interactiveinterpreter.cpp \
|
||||||
|
$$PWD/consoletreeview.cpp \
|
||||||
|
$$PWD/consoleitemmodel.cpp \
|
||||||
|
$$PWD/consoleitemdelegate.cpp \
|
||||||
|
$$PWD/consoleeditor.cpp \
|
||||||
|
$$PWD/consolebackend.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -31,20 +31,21 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "qmljsscriptconsole.h"
|
#include "qmljsscriptconsole.h"
|
||||||
#include "interactiveinterpreter.h"
|
|
||||||
#include "qmladapter.h"
|
#include "qmladapter.h"
|
||||||
#include "debuggerstringutils.h"
|
#include "debuggerstringutils.h"
|
||||||
|
#include "consoletreeview.h"
|
||||||
#include <texteditor/fontsettings.h>
|
#include "consoleitemmodel.h"
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include "consoleitemdelegate.h"
|
||||||
|
#include "consolebackend.h"
|
||||||
|
#include "debuggerstringutils.h"
|
||||||
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
#include <utils/statuslabel.h>
|
#include <utils/statuslabel.h>
|
||||||
#include <utils/styledbar.h>
|
#include <utils/styledbar.h>
|
||||||
|
#include <utils/savedaction.h>
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
|
|
||||||
#include <qmljsdebugclient/qdebugmessageclient.h>
|
#include <qmljsdebugclient/qdebugmessageclient.h>
|
||||||
#include <debugger/qml/qmlcppengine.h>
|
#include <debugger/qml/qmlcppengine.h>
|
||||||
@@ -67,56 +68,6 @@ static const char SHOW_ERROR[] = "showError";
|
|||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class QmlJSScriptConsolePrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QmlJSScriptConsolePrivate()
|
|
||||||
: adapter(0),
|
|
||||||
prompt(_("> ")),
|
|
||||||
startOfEditableArea(-1),
|
|
||||||
lastKnownPosition(0),
|
|
||||||
inferiorStopped(false),
|
|
||||||
hasContext(false)
|
|
||||||
{
|
|
||||||
scriptHistory.append(QString());
|
|
||||||
scriptHistoryIndex = scriptHistory.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
void appendToHistory(const QString &script);
|
|
||||||
bool canEvaluateScript(const QString &script);
|
|
||||||
|
|
||||||
QmlAdapter *adapter;
|
|
||||||
|
|
||||||
QString prompt;
|
|
||||||
int startOfEditableArea;
|
|
||||||
int lastKnownPosition;
|
|
||||||
|
|
||||||
QStringList scriptHistory;
|
|
||||||
int scriptHistoryIndex;
|
|
||||||
|
|
||||||
InteractiveInterpreter interpreter;
|
|
||||||
|
|
||||||
bool inferiorStopped;
|
|
||||||
bool hasContext;
|
|
||||||
|
|
||||||
QFlags<QmlJSScriptConsole::DebugLevelFlag> debugLevel;
|
|
||||||
};
|
|
||||||
|
|
||||||
void QmlJSScriptConsolePrivate::appendToHistory(const QString &script)
|
|
||||||
{
|
|
||||||
scriptHistoryIndex = scriptHistory.count();
|
|
||||||
scriptHistory.replace(scriptHistoryIndex - 1,script);
|
|
||||||
scriptHistory.append(QString());
|
|
||||||
scriptHistoryIndex = scriptHistory.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QmlJSScriptConsolePrivate::canEvaluateScript(const QString &script)
|
|
||||||
{
|
|
||||||
interpreter.clearText();
|
|
||||||
interpreter.appendText(script);
|
|
||||||
return interpreter.canEvaluate();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// QmlJSScriptConsoleWidget
|
// QmlJSScriptConsoleWidget
|
||||||
@@ -126,74 +77,151 @@ bool QmlJSScriptConsolePrivate::canEvaluateScript(const QString &script)
|
|||||||
QmlJSScriptConsoleWidget::QmlJSScriptConsoleWidget(QWidget *parent)
|
QmlJSScriptConsoleWidget::QmlJSScriptConsoleWidget(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
|
const int statusBarHeight = 25;
|
||||||
|
const int spacing = 7;
|
||||||
|
const int buttonWidth = 25;
|
||||||
|
|
||||||
QVBoxLayout *vbox = new QVBoxLayout(this);
|
QVBoxLayout *vbox = new QVBoxLayout(this);
|
||||||
vbox->setMargin(0);
|
vbox->setMargin(0);
|
||||||
vbox->setSpacing(0);
|
vbox->setSpacing(0);
|
||||||
|
|
||||||
QWidget *statusbarContainer = new QWidget;
|
QWidget *statusbarContainer = new QWidget;
|
||||||
|
statusbarContainer->setFixedHeight(statusBarHeight);
|
||||||
QHBoxLayout *hbox = new QHBoxLayout(statusbarContainer);
|
QHBoxLayout *hbox = new QHBoxLayout(statusbarContainer);
|
||||||
hbox->setMargin(0);
|
hbox->setMargin(0);
|
||||||
hbox->setSpacing(0);
|
hbox->setSpacing(0);
|
||||||
|
|
||||||
//Clear Button
|
|
||||||
QToolButton *clearButton = new QToolButton;
|
|
||||||
QAction *clearAction = new QAction(tr("Clear Console"), this);
|
|
||||||
clearAction->setIcon(QIcon(_(Core::Constants::ICON_CLEAN_PANE)));
|
|
||||||
|
|
||||||
clearButton->setDefaultAction(clearAction);
|
|
||||||
|
|
||||||
//Status Label
|
//Status Label
|
||||||
m_statusLabel = new Utils::StatusLabel;
|
m_statusLabel = new Utils::StatusLabel;
|
||||||
|
hbox->addSpacing(spacing);
|
||||||
hbox->addWidget(m_statusLabel, 20, Qt::AlignLeft);
|
hbox->addWidget(m_statusLabel);
|
||||||
hbox->addWidget(new Utils::StyledSeparator);
|
hbox->addWidget(new Utils::StyledSeparator);
|
||||||
m_showLog = new QCheckBox(tr("Log"), this);
|
|
||||||
m_showWarning = new QCheckBox(tr("Warning"), this);
|
//Filters
|
||||||
m_showError = new QCheckBox(tr("Error"), this);
|
hbox->addSpacing(spacing);
|
||||||
connect(m_showLog, SIGNAL(stateChanged(int)), this, SLOT(setDebugLevel()));
|
m_showLog = new QToolButton(this);
|
||||||
connect(m_showWarning, SIGNAL(stateChanged(int)), this, SLOT(setDebugLevel()));
|
m_showLog->setAutoRaise(true);
|
||||||
connect(m_showError, SIGNAL(stateChanged(int)), this, SLOT(setDebugLevel()));
|
m_showLog->setFixedWidth(buttonWidth);
|
||||||
|
m_showLogAction = new Utils::SavedAction(this);
|
||||||
|
m_showLogAction->setDefaultValue(true);
|
||||||
|
m_showLogAction->setSettingsKey(_(SCRIPT_CONSOLE), _(SHOW_LOG));
|
||||||
|
m_showLogAction->setText(tr("Log"));
|
||||||
|
m_showLogAction->setCheckable(true);
|
||||||
|
m_showLogAction->setIcon(QIcon(_(":/debugger/images/log.png")));
|
||||||
|
// connect(m_showLogAction, SIGNAL(toggled(bool)), this, SLOT(setDebugLevel()));
|
||||||
|
m_showLog->setDefaultAction(m_showLogAction);
|
||||||
|
|
||||||
|
m_showWarning = new QToolButton(this);
|
||||||
|
m_showWarning->setAutoRaise(true);
|
||||||
|
m_showWarning->setFixedWidth(buttonWidth);
|
||||||
|
m_showWarningAction = new Utils::SavedAction(this);
|
||||||
|
m_showWarningAction->setDefaultValue(true);
|
||||||
|
m_showWarningAction->setSettingsKey(_(SCRIPT_CONSOLE), _(SHOW_WARNING));
|
||||||
|
m_showWarningAction->setText(tr("Warning"));
|
||||||
|
m_showWarningAction->setCheckable(true);
|
||||||
|
m_showWarningAction->setIcon(QIcon(_(":/debugger/images/warning.png")));
|
||||||
|
// connect(m_showWarningAction, SIGNAL(toggled(bool)), this, SLOT(setDebugLevel()));
|
||||||
|
m_showWarning->setDefaultAction(m_showWarningAction);
|
||||||
|
|
||||||
|
m_showError = new QToolButton(this);
|
||||||
|
m_showError->setAutoRaise(true);
|
||||||
|
m_showError->setFixedWidth(buttonWidth);
|
||||||
|
m_showErrorAction = new Utils::SavedAction(this);
|
||||||
|
m_showErrorAction->setDefaultValue(true);
|
||||||
|
m_showErrorAction->setSettingsKey(_(SCRIPT_CONSOLE), _(SHOW_ERROR));
|
||||||
|
m_showErrorAction->setText(tr("Error"));
|
||||||
|
m_showErrorAction->setCheckable(true);
|
||||||
|
m_showErrorAction->setIcon(QIcon(_(":/debugger/images/error.png")));
|
||||||
|
// connect(m_showErrorAction, SIGNAL(toggled(bool)), this, SLOT(setDebugLevel()));
|
||||||
|
m_showError->setDefaultAction(m_showErrorAction);
|
||||||
|
|
||||||
hbox->addWidget(m_showLog);
|
hbox->addWidget(m_showLog);
|
||||||
|
hbox->addSpacing(spacing);
|
||||||
hbox->addWidget(m_showWarning);
|
hbox->addWidget(m_showWarning);
|
||||||
|
hbox->addSpacing(spacing);
|
||||||
hbox->addWidget(m_showError);
|
hbox->addWidget(m_showError);
|
||||||
hbox->addWidget(new Utils::StyledSeparator);
|
|
||||||
hbox->addWidget(clearButton, 0, Qt::AlignRight);
|
|
||||||
|
|
||||||
m_console = new QmlJSScriptConsole(this);
|
//Clear Button
|
||||||
connect(m_console, SIGNAL(evaluateExpression(QString)), this,
|
QToolButton *clearButton = new QToolButton;
|
||||||
SIGNAL(evaluateExpression(QString)));
|
clearButton->setAutoRaise(true);
|
||||||
connect(m_console, SIGNAL(updateStatusMessage(const QString &, int)), m_statusLabel,
|
clearButton->setFixedWidth(buttonWidth);
|
||||||
SLOT(showStatusMessage(const QString &, int)));
|
QAction *clearAction = new QAction(tr("Clear Console"), this);
|
||||||
connect(clearAction, SIGNAL(triggered()), m_console, SLOT(clear()));
|
clearAction->setIcon(QIcon(_(Core::Constants::ICON_CLEAN_PANE)));
|
||||||
|
clearButton->setDefaultAction(clearAction);
|
||||||
|
|
||||||
|
hbox->addSpacing(spacing);
|
||||||
|
hbox->addWidget(clearButton);
|
||||||
|
hbox->addSpacing(spacing);
|
||||||
|
|
||||||
|
m_consoleView = new ConsoleTreeView(this);
|
||||||
|
|
||||||
|
m_model = new ConsoleItemModel(this);
|
||||||
|
m_model->clear();
|
||||||
|
connect(clearAction, SIGNAL(triggered()), m_model, SLOT(clear()));
|
||||||
|
m_consoleView->setModel(m_model);
|
||||||
|
connect(m_model,
|
||||||
|
SIGNAL(editableRowAppended(QModelIndex,QItemSelectionModel::SelectionFlags)),
|
||||||
|
m_consoleView->selectionModel(),
|
||||||
|
SLOT(setCurrentIndex(QModelIndex,QItemSelectionModel::SelectionFlags)));
|
||||||
|
|
||||||
|
m_consoleBackend = new QmlJSConsoleBackend(this);
|
||||||
|
connect(m_consoleBackend, SIGNAL(evaluateExpression(QString)),
|
||||||
|
this, SIGNAL(evaluateExpression(QString)));
|
||||||
|
connect(m_consoleBackend, SIGNAL(message(ConsoleItemModel::ItemType,QString)),
|
||||||
|
this, SLOT(appendOutput(ConsoleItemModel::ItemType,QString)));
|
||||||
|
|
||||||
|
m_itemDelegate = new ConsoleItemDelegate(this);
|
||||||
|
connect(m_itemDelegate, SIGNAL(appendEditableRow()),
|
||||||
|
m_model, SLOT(appendEditableRow()));
|
||||||
|
m_itemDelegate->setConsoleBackend(m_consoleBackend);
|
||||||
|
m_consoleView->setItemDelegate(m_itemDelegate);
|
||||||
|
|
||||||
vbox->addWidget(statusbarContainer);
|
vbox->addWidget(statusbarContainer);
|
||||||
vbox->addWidget(m_console);
|
vbox->addWidget(m_consoleView);
|
||||||
|
|
||||||
QSettings *settings = Core::ICore::settings();
|
readSettings();
|
||||||
settings->beginGroup(_(SCRIPT_CONSOLE));
|
connect(Core::ICore::instance(),
|
||||||
m_showLog->setChecked(settings->value(_(SHOW_LOG), true).toBool());
|
SIGNAL(saveSettingsRequested()), SLOT(writeSettings()));
|
||||||
m_showWarning->setChecked(settings->value(_(SHOW_WARNING), true).toBool());
|
|
||||||
m_showError->setChecked(settings->value(_(SHOW_ERROR), true).toBool());
|
|
||||||
settings->endGroup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlJSScriptConsoleWidget::~QmlJSScriptConsoleWidget()
|
QmlJSScriptConsoleWidget::~QmlJSScriptConsoleWidget()
|
||||||
|
{
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlJSScriptConsoleWidget::readSettings()
|
||||||
{
|
{
|
||||||
QSettings *settings = Core::ICore::settings();
|
QSettings *settings = Core::ICore::settings();
|
||||||
settings->beginGroup(_(SCRIPT_CONSOLE));
|
m_showLogAction->readSettings(settings);
|
||||||
settings->setValue(_(SHOW_LOG), QVariant(m_showLog->isChecked()));
|
m_showWarningAction->readSettings(settings);
|
||||||
settings->setValue(_(SHOW_WARNING), QVariant(m_showWarning->isChecked()));
|
m_showErrorAction->readSettings(settings);
|
||||||
settings->setValue(_(SHOW_ERROR), QVariant(m_showError->isChecked()));
|
}
|
||||||
settings->endGroup();
|
|
||||||
|
void QmlJSScriptConsoleWidget::writeSettings() const
|
||||||
|
{
|
||||||
|
QSettings *settings = Core::ICore::settings();
|
||||||
|
m_showLogAction->writeSettings(settings);
|
||||||
|
m_showWarningAction->writeSettings(settings);
|
||||||
|
m_showErrorAction->writeSettings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlJSScriptConsoleWidget::setEngine(DebuggerEngine *engine)
|
void QmlJSScriptConsoleWidget::setEngine(DebuggerEngine *engine)
|
||||||
{
|
{
|
||||||
if (m_console->engine())
|
QmlEngine *qmlEngine = m_consoleBackend->engine();
|
||||||
disconnect(m_console->engine(), SIGNAL(stateChanged(Debugger::DebuggerState)),
|
if (qmlEngine) {
|
||||||
|
disconnect(qmlEngine, SIGNAL(stateChanged(Debugger::DebuggerState)),
|
||||||
this, SLOT(onEngineStateChanged(Debugger::DebuggerState)));
|
this, SLOT(onEngineStateChanged(Debugger::DebuggerState)));
|
||||||
|
disconnect(qmlEngine->stackHandler(), SIGNAL(currentIndexChanged()),
|
||||||
|
this, SLOT(onSelectionChanged()));
|
||||||
|
disconnect(qmlEngine->adapter(), SIGNAL(selectionChanged()),
|
||||||
|
this, SLOT(onSelectionChanged()));
|
||||||
|
disconnect(qmlEngine->adapter()->messageClient(),
|
||||||
|
SIGNAL(message(QtMsgType,QString)),
|
||||||
|
this, SLOT(appendMessage(QtMsgType,QString)));
|
||||||
|
qmlEngine = 0;
|
||||||
|
}
|
||||||
|
|
||||||
QmlEngine *qmlEngine = qobject_cast<QmlEngine *>(engine);
|
qmlEngine = qobject_cast<QmlEngine *>(engine);
|
||||||
QmlCppEngine *qmlCppEngine = qobject_cast<QmlCppEngine *>(engine);
|
QmlCppEngine *qmlCppEngine = qobject_cast<QmlCppEngine *>(engine);
|
||||||
if (qmlCppEngine)
|
if (qmlCppEngine)
|
||||||
qmlEngine = qobject_cast<QmlEngine *>(qmlCppEngine->qmlEngine());
|
qmlEngine = qobject_cast<QmlEngine *>(qmlCppEngine->qmlEngine());
|
||||||
@@ -202,483 +230,97 @@ void QmlJSScriptConsoleWidget::setEngine(DebuggerEngine *engine)
|
|||||||
if (qmlEngine) {
|
if (qmlEngine) {
|
||||||
connect(qmlEngine, SIGNAL(stateChanged(Debugger::DebuggerState)),
|
connect(qmlEngine, SIGNAL(stateChanged(Debugger::DebuggerState)),
|
||||||
this, SLOT(onEngineStateChanged(Debugger::DebuggerState)));
|
this, SLOT(onEngineStateChanged(Debugger::DebuggerState)));
|
||||||
|
connect(qmlEngine->stackHandler(), SIGNAL(currentIndexChanged()),
|
||||||
|
this, SLOT(onSelectionChanged()));
|
||||||
|
connect(qmlEngine->adapter(), SIGNAL(selectionChanged()),
|
||||||
|
this, SLOT(onSelectionChanged()));
|
||||||
|
connect(qmlEngine->adapter()->messageClient(),
|
||||||
|
SIGNAL(message(QtMsgType,QString)),
|
||||||
|
this, SLOT(appendMessage(QtMsgType,QString)));
|
||||||
onEngineStateChanged(qmlEngine->state());
|
onEngineStateChanged(qmlEngine->state());
|
||||||
}
|
}
|
||||||
|
m_consoleBackend->setEngine(qmlEngine);
|
||||||
m_console->setEngine(qmlEngine);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlJSScriptConsoleWidget::appendResult(const QString &result)
|
void QmlJSScriptConsoleWidget::appendResult(const QString &result)
|
||||||
{
|
{
|
||||||
m_console->appendResult(result);
|
m_model->appendItem(ConsoleItemModel::UndefinedType, result);
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsoleWidget::setDebugLevel()
|
|
||||||
{
|
|
||||||
QFlags<QmlJSScriptConsole::DebugLevelFlag> level;
|
|
||||||
|
|
||||||
if (m_showLog->isChecked())
|
|
||||||
level |= QmlJSScriptConsole::Log;
|
|
||||||
|
|
||||||
if (m_showWarning->isChecked())
|
|
||||||
level |= QmlJSScriptConsole::Warning;
|
|
||||||
|
|
||||||
if (m_showError->isChecked())
|
|
||||||
level |= QmlJSScriptConsole::Error;
|
|
||||||
|
|
||||||
m_console->setDebugLevel(level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlJSScriptConsoleWidget::onEngineStateChanged(Debugger::DebuggerState state)
|
void QmlJSScriptConsoleWidget::onEngineStateChanged(Debugger::DebuggerState state)
|
||||||
{
|
{
|
||||||
if (state == InferiorRunOk || state == InferiorStopOk) {
|
if (state == InferiorRunOk || state == InferiorStopOk) {
|
||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
m_console->setInferiorStopped(state == InferiorStopOk);
|
m_consoleBackend->setInferiorStopped(state == InferiorStopOk);
|
||||||
} else {
|
} else {
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
void QmlJSScriptConsoleWidget::onSelectionChanged()
|
||||||
//
|
|
||||||
// QmlJSScriptConsole
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
QmlJSScriptConsole::QmlJSScriptConsole(QWidget *parent)
|
|
||||||
: QPlainTextEdit(parent),
|
|
||||||
d(new QmlJSScriptConsolePrivate())
|
|
||||||
{
|
{
|
||||||
connect(this, SIGNAL(cursorPositionChanged()), SLOT(onCursorPositionChanged()));
|
QmlEngine *qmlEngine = m_consoleBackend->engine();
|
||||||
|
if (qmlEngine && qmlEngine->adapter()) {
|
||||||
|
const QString context = m_consoleBackend->inferiorStopped() ?
|
||||||
|
qmlEngine->stackHandler()->currentFrame().function :
|
||||||
|
qmlEngine->adapter()->currentSelectedDisplayName();
|
||||||
|
|
||||||
setFrameStyle(QFrame::NoFrame);
|
m_consoleBackend->setIsValidContext(!context.isEmpty());
|
||||||
setUndoRedoEnabled(false);
|
m_statusLabel->showStatusMessage(tr("Context: ").append(context), 0);
|
||||||
setBackgroundVisible(false);
|
|
||||||
const TextEditor::FontSettings &fs = TextEditor::TextEditorSettings::instance()->fontSettings();
|
|
||||||
setFont(fs.font());
|
|
||||||
|
|
||||||
displayPrompt();
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlJSScriptConsole::~QmlJSScriptConsole()
|
|
||||||
{
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::setPrompt(const QString &prompt)
|
|
||||||
{
|
|
||||||
d->prompt = prompt;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QmlJSScriptConsole::prompt() const
|
|
||||||
{
|
|
||||||
return d->prompt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::setInferiorStopped(bool inferiorStopped)
|
|
||||||
{
|
|
||||||
d->inferiorStopped = inferiorStopped;
|
|
||||||
onSelectionChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::setEngine(QmlEngine *eng)
|
|
||||||
{
|
|
||||||
if (d->adapter) {
|
|
||||||
disconnect(engine()->stackHandler(), SIGNAL(currentIndexChanged()), this, SLOT(onSelectionChanged()));
|
|
||||||
disconnect(d->adapter, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
|
|
||||||
disconnect(d->adapter->messageClient(), SIGNAL(message(QtMsgType,QString)),
|
|
||||||
this, SLOT(insertDebugOutput(QtMsgType,QString)));
|
|
||||||
d->adapter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eng) {
|
|
||||||
d->adapter = eng->adapter();
|
|
||||||
connect(eng->stackHandler(), SIGNAL(currentIndexChanged()), this, SLOT(onSelectionChanged()));
|
|
||||||
connect(d->adapter, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
|
|
||||||
connect(d->adapter->messageClient(), SIGNAL(message(QtMsgType,QString)),
|
|
||||||
this, SLOT(insertDebugOutput(QtMsgType,QString)));
|
|
||||||
}
|
|
||||||
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
DebuggerEngine *QmlJSScriptConsole::engine() const
|
|
||||||
{
|
|
||||||
if (d->adapter)
|
|
||||||
return d->adapter->debuggerEngine();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::appendResult(const QString &message, const QColor &color)
|
|
||||||
{
|
|
||||||
QTextCharFormat resultFormat;
|
|
||||||
resultFormat.setForeground(color);
|
|
||||||
QTextCursor cur = textCursor();
|
|
||||||
|
|
||||||
cur.setPosition(d->startOfEditableArea - d->prompt.length());
|
|
||||||
cur.insertText(message, resultFormat);
|
|
||||||
cur.insertText(_("\n"));
|
|
||||||
|
|
||||||
QList<QTextEdit::ExtraSelection> selections = extraSelections();
|
|
||||||
QTextEdit::ExtraSelection sel;
|
|
||||||
sel.format = resultFormat;
|
|
||||||
sel.cursor = cur;
|
|
||||||
selections.append(sel);
|
|
||||||
|
|
||||||
setExtraSelections(selections);
|
|
||||||
|
|
||||||
d->startOfEditableArea += message.length() + 1; //1 for new line character
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::setDebugLevel(QFlags<DebugLevelFlag> level)
|
|
||||||
{
|
|
||||||
d->debugLevel = level;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::clear()
|
|
||||||
{
|
|
||||||
QPlainTextEdit::clear();
|
|
||||||
displayPrompt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::onStateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State state)
|
|
||||||
{
|
|
||||||
QDeclarativeDebugExpressionQuery *query = qobject_cast<QDeclarativeDebugExpressionQuery *>(sender());
|
|
||||||
|
|
||||||
if (query && state != QDeclarativeDebugQuery::Error) {
|
|
||||||
QString result(query->result().toString());
|
|
||||||
if (result == _("<undefined>") && d->inferiorStopped) {
|
|
||||||
//don't give up. check if we can still evaluate using javascript engine
|
|
||||||
emit evaluateExpression(getCurrentScript());
|
|
||||||
} else {
|
|
||||||
appendResult(result);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QPlainTextEdit::appendPlainText(QString());
|
|
||||||
moveCursor(QTextCursor::EndOfLine);
|
|
||||||
}
|
|
||||||
delete query;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::onSelectionChanged()
|
|
||||||
{
|
|
||||||
if (d->adapter) {
|
|
||||||
const QString context = d->inferiorStopped ?
|
|
||||||
d->adapter->debuggerEngine()->stackHandler()->currentFrame().function :
|
|
||||||
d->adapter->currentSelectedDisplayName();
|
|
||||||
|
|
||||||
d->hasContext = !context.isEmpty();
|
|
||||||
emit updateStatusMessage(tr("Context: ").append(context), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlJSScriptConsole::insertDebugOutput(QtMsgType type, const QString &debugMsg)
|
void QmlJSScriptConsoleWidget::appendOutput(ConsoleItemModel::ItemType itemType,
|
||||||
|
const QString &message)
|
||||||
{
|
{
|
||||||
QColor color;
|
if (itemType == ConsoleItemModel::UndefinedType)
|
||||||
switch (type) {
|
return m_model->appendItem(itemType, message);
|
||||||
case QtDebugMsg:
|
|
||||||
if (!(d->debugLevel & Log))
|
QtMsgType type;
|
||||||
return;
|
switch (itemType) {
|
||||||
color = QColor(Qt::darkBlue);
|
case ConsoleItemModel::LogType:
|
||||||
|
type = QtDebugMsg;
|
||||||
break;
|
break;
|
||||||
case QtWarningMsg:
|
case ConsoleItemModel::WarningType:
|
||||||
if (!(d->debugLevel & Warning))
|
type = QtWarningMsg;
|
||||||
return;
|
|
||||||
color = QColor(Qt::darkYellow);
|
|
||||||
break;
|
break;
|
||||||
case QtCriticalMsg:
|
case ConsoleItemModel::ErrorType:
|
||||||
if (!(d->debugLevel & Error))
|
type = QtCriticalMsg;
|
||||||
return;
|
|
||||||
color = QColor(Qt::darkRed);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
color = QColor(Qt::black);
|
type = QtDebugMsg;
|
||||||
}
|
|
||||||
appendResult(debugMsg, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::keyPressEvent(QKeyEvent *e)
|
|
||||||
{
|
|
||||||
bool keyConsumed = false;
|
|
||||||
switch (e->key()) {
|
|
||||||
|
|
||||||
case Qt::Key_Return:
|
|
||||||
case Qt::Key_Enter:
|
|
||||||
if (isEditableArea()) {
|
|
||||||
handleReturnKey();
|
|
||||||
keyConsumed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::Key_Backspace: {
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
bool hasSelection = cursor.hasSelection();
|
|
||||||
int selectionStart = cursor.selectionStart();
|
|
||||||
if ((hasSelection && selectionStart < d->startOfEditableArea)
|
|
||||||
|| (!hasSelection && selectionStart == d->startOfEditableArea)) {
|
|
||||||
keyConsumed = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
appendMessage(type, message);
|
||||||
|
}
|
||||||
|
|
||||||
case Qt::Key_Delete:
|
void QmlJSScriptConsoleWidget::appendMessage(QtMsgType type, const QString &message)
|
||||||
if (textCursor().selectionStart() < d->startOfEditableArea) {
|
{
|
||||||
keyConsumed = true;
|
ConsoleItemModel::ItemType itemType;
|
||||||
}
|
switch (type) {
|
||||||
|
case QtDebugMsg:
|
||||||
|
if (!m_showLogAction->isChecked())
|
||||||
|
return;
|
||||||
|
itemType = ConsoleItemModel::LogType;
|
||||||
break;
|
break;
|
||||||
|
case QtWarningMsg:
|
||||||
case Qt::Key_Tab:
|
if (!m_showWarningAction->isChecked())
|
||||||
case Qt::Key_Backtab:
|
return;
|
||||||
keyConsumed = true;
|
itemType = ConsoleItemModel::WarningType;
|
||||||
break;
|
break;
|
||||||
|
case QtCriticalMsg:
|
||||||
case Qt::Key_Left:
|
case QtFatalMsg:
|
||||||
if (textCursor().position() == d->startOfEditableArea) {
|
if (!m_showErrorAction->isChecked())
|
||||||
keyConsumed = true;
|
return;
|
||||||
} else if (e->modifiers() & Qt::ControlModifier && isEditableArea()) {
|
itemType = ConsoleItemModel::ErrorType;
|
||||||
handleHomeKey();
|
|
||||||
keyConsumed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::Key_Up:
|
|
||||||
if (isEditableArea()) {
|
|
||||||
handleUpKey();
|
|
||||||
keyConsumed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::Key_Down:
|
|
||||||
if (isEditableArea()) {
|
|
||||||
handleDownKey();
|
|
||||||
keyConsumed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::Key_Home:
|
|
||||||
if (isEditableArea()) {
|
|
||||||
handleHomeKey();
|
|
||||||
keyConsumed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::Key_C:
|
|
||||||
case Qt::Key_Insert: {
|
|
||||||
//Fair to assume that for any selection beyond startOfEditableArea
|
|
||||||
//only copy function is allowed.
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
bool hasSelection = cursor.hasSelection();
|
|
||||||
int selectionStart = cursor.selectionStart();
|
|
||||||
if (hasSelection && selectionStart < d->startOfEditableArea) {
|
|
||||||
if (!(e->modifiers() & Qt::ControlModifier))
|
|
||||||
keyConsumed = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
//this cannot happen as type has to
|
||||||
|
//be one of the above
|
||||||
|
//return since itemType is not known
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
m_model->appendItem(itemType, message);
|
||||||
default: {
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
bool hasSelection = cursor.hasSelection();
|
|
||||||
int selectionStart = cursor.selectionStart();
|
|
||||||
if (hasSelection && selectionStart < d->startOfEditableArea) {
|
|
||||||
keyConsumed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!keyConsumed)
|
|
||||||
QPlainTextEdit::keyPressEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::contextMenuEvent(QContextMenuEvent *event)
|
|
||||||
{
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
Qt::TextInteractionFlags flags = textInteractionFlags();
|
|
||||||
bool hasSelection = cursor.hasSelection();
|
|
||||||
int selectionStart = cursor.selectionStart();
|
|
||||||
bool canBeEdited = true;
|
|
||||||
if (hasSelection && selectionStart < d->startOfEditableArea) {
|
|
||||||
canBeEdited = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMenu *menu = new QMenu();
|
|
||||||
QAction *a;
|
|
||||||
|
|
||||||
if ((flags & Qt::TextEditable) && canBeEdited) {
|
|
||||||
a = menu->addAction(tr("Cut"), this, SLOT(cut()));
|
|
||||||
a->setEnabled(cursor.hasSelection());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
a = menu->addAction(tr("Copy"), this, SLOT(copy()));
|
|
||||||
a->setEnabled(cursor.hasSelection());
|
|
||||||
|
|
||||||
if ((flags & Qt::TextEditable) && canBeEdited) {
|
|
||||||
a = menu->addAction(tr("Paste"), this, SLOT(paste()));
|
|
||||||
a->setEnabled(canPaste());
|
|
||||||
}
|
|
||||||
|
|
||||||
menu->addSeparator();
|
|
||||||
a = menu->addAction(tr("Select All"), this, SLOT(selectAll()));
|
|
||||||
a->setEnabled(!document()->isEmpty());
|
|
||||||
|
|
||||||
menu->addSeparator();
|
|
||||||
menu->addAction(tr("Clear"), this, SLOT(clear()));
|
|
||||||
|
|
||||||
menu->exec(event->globalPos());
|
|
||||||
|
|
||||||
|
|
||||||
delete menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::mouseReleaseEvent(QMouseEvent *e)
|
|
||||||
{
|
|
||||||
QPlainTextEdit::mouseReleaseEvent(e);
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
if (e->button() == Qt::LeftButton && !cursor.hasSelection() && !isEditableArea()) {
|
|
||||||
cursor.setPosition(d->lastKnownPosition);
|
|
||||||
setTextCursor(cursor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::onCursorPositionChanged()
|
|
||||||
{
|
|
||||||
if (!isEditableArea()) {
|
|
||||||
setTextInteractionFlags(Qt::TextSelectableByMouse);
|
|
||||||
} else {
|
|
||||||
d->lastKnownPosition = textCursor().position();
|
|
||||||
setTextInteractionFlags(Qt::TextEditorInteraction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::displayPrompt()
|
|
||||||
{
|
|
||||||
d->startOfEditableArea = textCursor().position() + d->prompt.length();
|
|
||||||
QTextCursor cur = textCursor();
|
|
||||||
cur.insertText(d->prompt);
|
|
||||||
cur.movePosition(QTextCursor::EndOfWord);
|
|
||||||
setTextCursor(cur);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::handleReturnKey()
|
|
||||||
{
|
|
||||||
QString currentScript = getCurrentScript();
|
|
||||||
bool showPrompt = true;
|
|
||||||
bool showInvalidContextError = false;
|
|
||||||
|
|
||||||
//Check if string is only white spaces
|
|
||||||
if (!currentScript.trimmed().isEmpty()) {
|
|
||||||
//Check for a valid context
|
|
||||||
if (d->hasContext) {
|
|
||||||
//check if it can be evaluated
|
|
||||||
if (d->canEvaluateScript(currentScript)) {
|
|
||||||
//Evaluate expression based on engine state
|
|
||||||
//When engine->state() == InferiorStopOk, the expression
|
|
||||||
//is sent to V8DebugService. In all other cases, the
|
|
||||||
//expression is evaluated by QDeclarativeEngine.
|
|
||||||
if (!d->inferiorStopped) {
|
|
||||||
QTC_ASSERT(d->adapter, return);
|
|
||||||
QDeclarativeEngineDebug *engineDebug = d->adapter->engineDebugClient();
|
|
||||||
int id = d->adapter->currentSelectedDebugId();
|
|
||||||
if (engineDebug && id != -1) {
|
|
||||||
QDeclarativeDebugExpressionQuery *query =
|
|
||||||
engineDebug->queryExpressionResult(id, currentScript, this);
|
|
||||||
connect(query, SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)),
|
|
||||||
this, SLOT(onStateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
emit evaluateExpression(currentScript);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->appendToHistory(currentScript);
|
|
||||||
} else {
|
|
||||||
//The expression is not complete, wait for more input
|
|
||||||
//Move to next line and do not show prompt
|
|
||||||
QPlainTextEdit::appendPlainText(QString());
|
|
||||||
moveCursor(QTextCursor::EndOfLine);
|
|
||||||
showPrompt = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Incase of invalid context, append the expression to history
|
|
||||||
//and show Error message
|
|
||||||
d->appendToHistory(currentScript);
|
|
||||||
showInvalidContextError = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showPrompt) {
|
|
||||||
QTextCursor cur = textCursor();
|
|
||||||
cur.movePosition(QTextCursor::End);
|
|
||||||
cur.insertText(_("\n"));
|
|
||||||
setTextCursor(cur);
|
|
||||||
displayPrompt();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Show an error message
|
|
||||||
if (showInvalidContextError)
|
|
||||||
appendResult(QLatin1String("Cannot evaluate without a valid QML/JS Context"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::handleUpKey()
|
|
||||||
{
|
|
||||||
//get the current script and update in script history
|
|
||||||
QString currentScript = getCurrentScript();
|
|
||||||
d->scriptHistory.replace(d->scriptHistoryIndex - 1,currentScript);
|
|
||||||
|
|
||||||
if (d->scriptHistoryIndex > 1)
|
|
||||||
d->scriptHistoryIndex--;
|
|
||||||
|
|
||||||
replaceCurrentScript(d->scriptHistory.at(d->scriptHistoryIndex - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::handleDownKey()
|
|
||||||
{
|
|
||||||
//get the current script and update in script history
|
|
||||||
QString currentScript = getCurrentScript();
|
|
||||||
d->scriptHistory.replace(d->scriptHistoryIndex - 1,currentScript);
|
|
||||||
|
|
||||||
if (d->scriptHistoryIndex < d->scriptHistory.count())
|
|
||||||
d->scriptHistoryIndex++;
|
|
||||||
|
|
||||||
replaceCurrentScript(d->scriptHistory.at(d->scriptHistoryIndex - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::handleHomeKey()
|
|
||||||
{
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
cursor.setPosition(d->startOfEditableArea);
|
|
||||||
setTextCursor(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QmlJSScriptConsole::getCurrentScript() const
|
|
||||||
{
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
cursor.setPosition(d->startOfEditableArea);
|
|
||||||
while (cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor)) ;
|
|
||||||
QString script = cursor.selectedText();
|
|
||||||
cursor.clearSelection();
|
|
||||||
//remove trailing white space
|
|
||||||
int end = script.size() - 1;
|
|
||||||
while (end > 0 && script[end].isSpace())
|
|
||||||
end--;
|
|
||||||
return script.left(end + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlJSScriptConsole::replaceCurrentScript(const QString &script)
|
|
||||||
{
|
|
||||||
QTextCursor cursor = textCursor();
|
|
||||||
cursor.setPosition(d->startOfEditableArea);
|
|
||||||
while (cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor)) ;
|
|
||||||
cursor.deleteChar();
|
|
||||||
cursor.insertText(script);
|
|
||||||
setTextCursor(cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QmlJSScriptConsole::isEditableArea() const
|
|
||||||
{
|
|
||||||
return textCursor().position() >= d->startOfEditableArea;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} //Internal
|
} //Internal
|
||||||
|
|||||||
@@ -33,16 +33,17 @@
|
|||||||
#ifndef QMLJSSCRIPTCONSOLE_H
|
#ifndef QMLJSSCRIPTCONSOLE_H
|
||||||
#define QMLJSSCRIPTCONSOLE_H
|
#define QMLJSSCRIPTCONSOLE_H
|
||||||
|
|
||||||
#include <qmljsdebugclient/qdeclarativeenginedebug.h>
|
#include "consoleitemmodel.h"
|
||||||
#include <debugger/debuggerconstants.h>
|
#include <debugger/debuggerconstants.h>
|
||||||
#include <QPlainTextEdit>
|
#include <QtGui/QWidget>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QCheckBox;
|
class QToolButton;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
class StatusLabel;
|
class StatusLabel;
|
||||||
|
class SavedAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
@@ -51,10 +52,9 @@ class DebuggerEngine;
|
|||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class QmlJSScriptConsolePrivate;
|
class ConsoleTreeView;
|
||||||
class QmlJSScriptConsole;
|
class ConsoleItemDelegate;
|
||||||
class QmlEngine;
|
class QmlJSConsoleBackend;
|
||||||
|
|
||||||
class QmlJSScriptConsoleWidget : public QWidget
|
class QmlJSScriptConsoleWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -63,90 +63,33 @@ public:
|
|||||||
~QmlJSScriptConsoleWidget();
|
~QmlJSScriptConsoleWidget();
|
||||||
|
|
||||||
void setEngine(DebuggerEngine *engine);
|
void setEngine(DebuggerEngine *engine);
|
||||||
|
void readSettings();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void writeSettings() const;
|
||||||
void appendResult(const QString &result);
|
void appendResult(const QString &result);
|
||||||
|
void appendOutput(ConsoleItemModel::ItemType, const QString &message);
|
||||||
|
void appendMessage(QtMsgType type, const QString &message);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void evaluateExpression(const QString &expr);
|
void evaluateExpression(const QString &expr);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void setDebugLevel();
|
|
||||||
void onEngineStateChanged(Debugger::DebuggerState state);
|
void onEngineStateChanged(Debugger::DebuggerState state);
|
||||||
|
|
||||||
private:
|
|
||||||
QmlJSScriptConsole *m_console;
|
|
||||||
Utils::StatusLabel *m_statusLabel;
|
|
||||||
QCheckBox *m_showLog;
|
|
||||||
QCheckBox *m_showWarning;
|
|
||||||
QCheckBox *m_showError;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class QmlJSScriptConsole : public QPlainTextEdit
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum DebugLevelFlag {
|
|
||||||
None = 0,
|
|
||||||
Log = 1,
|
|
||||||
Warning = 2,
|
|
||||||
Error = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit QmlJSScriptConsole(QWidget *parent = 0);
|
|
||||||
~QmlJSScriptConsole();
|
|
||||||
|
|
||||||
inline void setTitle(const QString &title)
|
|
||||||
{ setDocumentTitle(title); }
|
|
||||||
|
|
||||||
inline QString title() const
|
|
||||||
{ return documentTitle(); }
|
|
||||||
|
|
||||||
void setPrompt(const QString &prompt);
|
|
||||||
QString prompt() const;
|
|
||||||
|
|
||||||
void setInferiorStopped(bool inferiorStopped);
|
|
||||||
|
|
||||||
void setEngine(QmlEngine *engine);
|
|
||||||
DebuggerEngine *engine() const;
|
|
||||||
|
|
||||||
void appendResult(const QString &message, const QColor &color = QColor(Qt::darkGray));
|
|
||||||
|
|
||||||
void setDebugLevel(QFlags<DebugLevelFlag> level);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void clear();
|
|
||||||
void onStateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State);
|
|
||||||
void insertDebugOutput(QtMsgType type, const QString &debugMsg);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void keyPressEvent(QKeyEvent *e);
|
|
||||||
void contextMenuEvent(QContextMenuEvent *event);
|
|
||||||
void mouseReleaseEvent(QMouseEvent *e);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void evaluateExpression(const QString &expr);
|
|
||||||
void updateStatusMessage(const QString &message, int timeoutMS);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onSelectionChanged();
|
void onSelectionChanged();
|
||||||
void onCursorPositionChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void displayPrompt();
|
ConsoleTreeView *m_consoleView;
|
||||||
void handleReturnKey();
|
ConsoleItemModel *m_model;
|
||||||
void handleUpKey();
|
ConsoleItemDelegate *m_itemDelegate;
|
||||||
void handleDownKey();
|
QmlJSConsoleBackend *m_consoleBackend;
|
||||||
void handleHomeKey();
|
Utils::StatusLabel *m_statusLabel;
|
||||||
QString getCurrentScript() const;
|
QToolButton *m_showLog;
|
||||||
void replaceCurrentScript(const QString &script);
|
QToolButton *m_showWarning;
|
||||||
bool isEditableArea() const;
|
QToolButton *m_showError;
|
||||||
|
Utils::SavedAction *m_showLogAction;
|
||||||
private:
|
Utils::SavedAction *m_showWarningAction;
|
||||||
QmlJSScriptConsolePrivate *d;
|
Utils::SavedAction *m_showErrorAction;
|
||||||
friend class QmlJSScriptConsolePrivate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} //Internal
|
} //Internal
|
||||||
|
|||||||
Reference in New Issue
Block a user