QmlJSScriptConsole: Refactored ScriptConsole, added functionality.

The ScriptConsole is renamed to QmlJSScriptConsole. The console can be used
to evaluate expressions during a QML application debug session.
Changes:
* Console can be used even when application is not on a debug break
* The object context is the currently selected object in Inspector
* ContextMenu has a Clear option
* Multiple line expressions are supported
* Traverse Command History using up and down arrow keys

Change-Id: I4e1cd8763d60be43dbba395ead2a9a086d6bab7d
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
This commit is contained in:
Aurindam Jana
2011-10-06 17:38:28 +02:00
parent 87943ca61c
commit cb0b3424b3
17 changed files with 930 additions and 326 deletions

View File

@@ -170,7 +170,7 @@ public:
bool isWaiting() const;
Q_SIGNALS:
void stateChanged(QDeclarativeDebugQuery::State);
void stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State);
protected:
QDeclarativeDebugQuery(QObject *);

View File

@@ -6,3 +6,4 @@ include(../../plugins/texteditor/texteditor.pri)
include(../../libs/cplusplus/cplusplus.pri)
include(../../libs/utils/utils.pri)
include(../../libs/symbianutils/symbianutils.pri)
include(../../libs/qmljs/qmljs.pri)

View File

@@ -112,7 +112,7 @@
#include <utils/statuslabel.h>
#include <utils/fileutils.h>
#include <qml/scriptconsole.h>
#include <qml/qmljsscriptconsole.h>
#include <QtCore/QTimer>
#include <QtCore/QtPlugin>
@@ -785,7 +785,7 @@ public slots:
void aboutToSaveSession();
void executeDebuggerCommand(const QString &command);
void scriptExpressionEntered(const QString &expression);
void evaluateExpression(const QString &expression);
void coreShutdown();
public slots:
@@ -1079,7 +1079,7 @@ public:
QAbstractItemView *m_stackWindow;
QAbstractItemView *m_threadsWindow;
LogWindow *m_logWindow;
ScriptConsole *m_scriptConsoleWindow;
QmlJSScriptConsoleWidget *m_scriptConsoleWindow;
bool m_busy;
QString m_lastPermanentStatusMessage;
@@ -1972,6 +1972,16 @@ void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine)
//m_threadBox->setModel(engine->threadsModel());
//m_threadBox->setModelColumn(ThreadData::ComboNameColumn);
m_watchersWindow->setModel(engine->watchersModel());
//Initialize QmlJSConsole
QmlEngine *qmlEngine = qobject_cast<QmlEngine *>(engine);
QmlCppEngine *qmlCppEngine = qobject_cast<QmlCppEngine *>(engine);
if (qmlCppEngine)
qmlEngine = qobject_cast<QmlEngine *>(qmlCppEngine->qmlEngine());
if (qmlEngine) {
m_scriptConsoleWindow->setQmlAdapter(qmlEngine->adapter());
}
engine->watchHandler()->rebuildModel();
}
@@ -2047,7 +2057,6 @@ void DebuggerPluginPrivate::setBusyCursor(bool busy)
m_threadsWindow->setCursor(cursor);
m_watchersWindow->setCursor(cursor);
m_snapshotWindow->setCursor(cursor);
m_scriptConsoleWindow->setCursor(cursor);
}
void DebuggerPluginPrivate::setInitialState()
@@ -2239,8 +2248,11 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
if (qmlCppEngine)
qmlEngine = qobject_cast<QmlEngine *>(qmlCppEngine->qmlEngine());
if (qmlEngine) {
m_scriptConsoleWindow->setEnabled(stopped);
if (qmlEngine && (state == InferiorRunOk || state == InferiorStopOk)) {
m_scriptConsoleWindow->setEnabled(true);
m_scriptConsoleWindow->setInferiorStopped(state == InferiorStopOk);
} else {
m_scriptConsoleWindow->setEnabled(false);
}
}
@@ -2387,7 +2399,7 @@ void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
m_statusLabel->showStatusMessage(msg, timeout);
}
void DebuggerPluginPrivate::scriptExpressionEntered(const QString &expression)
void DebuggerPluginPrivate::evaluateExpression(const QString &expression)
{
currentEngine()->executeDebuggerCommand(expression);
}
@@ -2757,11 +2769,11 @@ void DebuggerPluginPrivate::extensionsInitialized()
m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
m_watchersWindow = new WatchWindow(WatchWindow::WatchersType);
m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
m_scriptConsoleWindow = new ScriptConsole;
m_scriptConsoleWindow = new QmlJSScriptConsoleWidget;
m_scriptConsoleWindow->setWindowTitle(tr("QML Script Console"));
m_scriptConsoleWindow->setObjectName(DOCKWIDGET_QML_SCRIPTCONSOLE);
connect(m_scriptConsoleWindow, SIGNAL(expressionEntered(QString)),
SLOT(scriptExpressionEntered(QString)));
connect(m_scriptConsoleWindow, SIGNAL(evaluateExpression(QString)),
SLOT(evaluateExpression(QString)));
// Snapshot
m_snapshotHandler = new SnapshotHandler;

View File

@@ -0,0 +1,90 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.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 info@qt.nokia.com.
**
**************************************************************************/
#include "interactiveinterpreter.h"
namespace Debugger {
namespace Internal {
bool InteractiveInterpreter::canEvaluate()
{
int yyaction = 0;
int yytoken = -1;
int yytos = -1;
setCode(m_code, 1);
m_tokens.append(T_FEED_JS_PROGRAM);
do {
if (++yytos == m_stateStack.size())
m_stateStack.resize(m_stateStack.size() * 2);
m_stateStack[yytos] = yyaction;
again:
if (yytoken == -1 && action_index[yyaction] != -TERMINAL_COUNT) {
if (m_tokens.isEmpty())
yytoken = lex();
else
yytoken = m_tokens.takeFirst();
}
yyaction = t_action(yyaction, yytoken);
if (yyaction > 0) {
if (yyaction == ACCEPT_STATE) {
--yytos;
return true;
}
yytoken = -1;
} else if (yyaction < 0) {
const int ruleno = -yyaction - 1;
yytos -= rhs[ruleno];
yyaction = nt_action(m_stateStack[yytos], lhs[ruleno] - TERMINAL_COUNT);
}
} while (yyaction);
const int errorState = m_stateStack[yytos];
if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && canInsertAutomaticSemicolon(yytoken)) {
yyaction = errorState;
m_tokens.prepend(yytoken);
yytoken = T_SEMICOLON;
goto again;
}
if (yytoken != EOF_SYMBOL)
return true;
return false;
}
}
}

View File

@@ -30,57 +30,42 @@
**
**************************************************************************/
#ifndef QMLJSSCRIPTCONSOLE_H
#define QMLJSSCRIPTCONSOLE_H
#ifndef INTERACTIVEINTERPRETER_H
#define INTERACTIVEINTERPRETER_H
#include <QtGui/QWidget>
#include <QtGui/QToolButton>
#include <QtGui/QPlainTextEdit>
#include <qmljs/parser/qmljslexer_p.h>
#include <qmljs/parser/qmljsengine_p.h>
#include <utils/fancylineedit.h>
namespace QmlJSEditor {
class Highlighter;
}
#include <QtCore/QVector>
#include <QtCore/QString>
#include <QtCore/QList>
namespace Debugger {
namespace Internal {
class ScriptConsole : public QWidget
class InteractiveInterpreter: QmlJS::Lexer
{
Q_OBJECT
public:
ScriptConsole(QWidget *parent = 0);
InteractiveInterpreter()
: Lexer(&m_engine),
m_stateStack(128)
{
public slots:
void appendResult(const QString &result);
signals:
void expressionEntered(const QString &expr);
}
protected slots:
void clearTextEditor();
void executeExpression();
void clearText() { m_code.clear(); }
void appendText(const QString &text) { m_code += text; }
protected:
bool eventFilter(QObject *obj, QEvent *event);
void setFontSettings();
void clear();
// QToolButton *m_clearButton;
QPlainTextEdit *m_textEdit;
Utils::FancyLineEdit *m_lineEdit;
QString m_prompt;
QString m_expr;
QString m_lastExpr;
QString m_title;
QmlJSEditor::Highlighter *m_highlighter;
QString code() const { return m_code; }
bool canEvaluate();
private:
QmlJS::Engine m_engine;
QVector<int> m_stateStack;
QList<int> m_tokens;
QString m_code;
};
}
} //end namespaces
#endif
}
#endif // INTERACTIVEINTERPRETER_H

View File

@@ -1,4 +1,5 @@
include($$PWD/../../../libs/qmljsdebugclient/qmljsdebugclient.pri)
include($$PWD/../../../libs/qmljs/parser/parser.pri)
include($$PWD/../../../shared/json/json.pri)
DEFINES += JSON_INCLUDE_PRI
@@ -8,15 +9,18 @@ HEADERS += \
$$PWD/qmldebuggerclient.h \
$$PWD/qmljsprivateapi.h \
$$PWD/qmlcppengine.h \
$$PWD/scriptconsole.h \
$$PWD/qmljsscriptconsole.h \
$$PWD/qscriptdebuggerclient.h \
$$PWD/qmlv8debuggerclient.h
$$PWD/qmlv8debuggerclient.h \
$$PWD/interactiveinterpreter.h
SOURCES += \
$$PWD/qmlengine.cpp \
$$PWD/qmladapter.cpp \
$$PWD/qmldebuggerclient.cpp \
$$PWD/qmlcppengine.cpp \
$$PWD/scriptconsole.cpp \
$$PWD/qmljsscriptconsole.cpp \
$$PWD/qscriptdebuggerclient.cpp \
$$PWD/qmlv8debuggerclient.cpp
$$PWD/qmlv8debuggerclient.cpp \
$$PWD/interactiveinterpreter.cpp

View File

@@ -54,7 +54,9 @@ public:
explicit QmlAdapterPrivate(DebuggerEngine *engine)
: m_engine(engine)
, m_qmlClient(0)
, m_engineDebugClient(0)
, m_conn(0)
, m_currentSelectedDebugId(-1)
{
m_connectionTimer.setInterval(4000);
m_connectionTimer.setSingleShot(true);
@@ -62,9 +64,12 @@ public:
QWeakPointer<DebuggerEngine> m_engine;
QmlDebuggerClient *m_qmlClient;
QmlJsDebugClient::QDeclarativeEngineDebug *m_engineDebugClient;
QTimer m_connectionTimer;
QDeclarativeDebugConnection *m_conn;
QHash<QString, QmlDebuggerClient*> debugClients;
int m_currentSelectedDebugId;
QString m_currentSelectedDebugName;
};
} // namespace Internal
@@ -272,6 +277,34 @@ QHash<QString, Internal::QmlDebuggerClient*> QmlAdapter::debuggerClients()
{
return d->debugClients;
}
QmlJsDebugClient::QDeclarativeEngineDebug *QmlAdapter::engineDebugClient() const
{
return d->m_engineDebugClient;
}
void QmlAdapter::setEngineDebugClient(QmlJsDebugClient::QDeclarativeEngineDebug *client)
{
d->m_engineDebugClient = client;
}
int QmlAdapter::currentSelectedDebugId() const
{
return d->m_currentSelectedDebugId;
}
QString QmlAdapter::currentSelectedDisplayName() const
{
return d->m_currentSelectedDebugName;
}
void QmlAdapter::setCurrentSelectedDebugInfo(int currentDebugId, const QString &displayName)
{
d->m_currentSelectedDebugId = currentDebugId;
d->m_currentSelectedDebugName = displayName;
emit selectionChanged();
}
void QmlAdapter::logServiceStatusChange(const QString &service,
QDeclarativeDebugClient::Status newStatus)
{

View File

@@ -73,6 +73,13 @@ public:
Internal::QmlDebuggerClient *activeDebuggerClient();
QHash<QString, Internal::QmlDebuggerClient*> debuggerClients();
QmlJsDebugClient::QDeclarativeEngineDebug *engineDebugClient() const;
void setEngineDebugClient(QmlJsDebugClient::QDeclarativeEngineDebug *client);
int currentSelectedDebugId() const;
QString currentSelectedDisplayName() const;
void setCurrentSelectedDebugInfo(int debugId, const QString &displayName = QString());
public slots:
void logServiceStatusChange(const QString &service, QDeclarativeDebugClient::Status newStatus);
void logServiceActivity(const QString &service, const QString &logMessage);
@@ -83,6 +90,7 @@ signals:
void connectionStartupFailed();
void connectionError(QAbstractSocket::SocketError socketError);
void serviceConnectionError(const QString serviceName);
void selectionChanged();
private slots:
void connectionErrorOccurred(QAbstractSocket::SocketError socketError);

View File

@@ -676,7 +676,7 @@ void QmlEngine::requestModuleSymbols(const QString &moduleName)
bool QmlEngine::setToolTipExpression(const QPoint &mousePos,
TextEditor::ITextEditor *editor, const DebuggerToolTipContext &ctx)
{
// This is processed by QML inspector, which has dependencies to
// This is processed by QML inspector, which has dependencies to
// the qml js editor. Makes life easier.
emit tooltipRequested(mousePos, editor, ctx.position);
return true;
@@ -811,6 +811,11 @@ void QmlEngine::logMessage(LogDirection direction, const QString &message)
showMessage(msg, LogDebug);
}
QmlAdapter *QmlEngine::adapter() const
{
return &d->m_adapter;
}
QmlEngine *createQmlEngine(const DebuggerStartParameters &sp,
DebuggerEngine *masterEngine)
{

View File

@@ -40,6 +40,9 @@
#include <QtNetwork/QAbstractSocket>
namespace Debugger {
class QmlAdapter;
namespace Internal {
class QmlEnginePrivate;
@@ -71,6 +74,8 @@ public:
void logMessage(LogDirection direction, const QString &str);
QmlAdapter *adapter() const;
public slots:
void disconnected();

View File

@@ -0,0 +1,552 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.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 info@qt.nokia.com.
**
**************************************************************************/
#include "qmljsscriptconsole.h"
#include "interactiveinterpreter.h"
#include "qmladapter.h"
#include "debuggerstringutils.h"
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorsettings.h>
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/coreconstants.h>
#include <utils/statuslabel.h>
#include <QtGui/QMenu>
#include <QtGui/QTextBlock>
#include <QtGui/QHBoxLayout>
#include <QtGui/QVBoxLayout>
#include <QtGui/QToolButton>
namespace Debugger {
namespace Internal {
class QmlJSScriptConsolePrivate
{
public:
QmlJSScriptConsolePrivate()
: prompt(QLatin1String("> ")),
startOfEditableArea(-1),
lastKnownPosition(0),
inferiorStopped(false)
{
resetCache();
}
void resetCache();
void appendToHistory(const QString &script);
bool canEvaluateScript(const QString &script);
QWeakPointer<QmlAdapter> adapter;
QString prompt;
int startOfEditableArea;
int lastKnownPosition;
QStringList scriptHistory;
int scriptHistoryIndex;
InteractiveInterpreter interpreter;
bool inferiorStopped;
QList<QTextEdit::ExtraSelection> selections;
};
void QmlJSScriptConsolePrivate::resetCache()
{
scriptHistory.clear();
scriptHistory.append(QLatin1String(""));
scriptHistoryIndex = scriptHistory.count();
selections.clear();
}
void QmlJSScriptConsolePrivate::appendToHistory(const QString &script)
{
scriptHistoryIndex = scriptHistory.count();
scriptHistory.replace(scriptHistoryIndex - 1,script);
scriptHistory.append(QLatin1String(""));
scriptHistoryIndex = scriptHistory.count();
}
bool QmlJSScriptConsolePrivate::canEvaluateScript(const QString &script)
{
interpreter.clearText();
interpreter.appendText(script);
return interpreter.canEvaluate();
}
///////////////////////////////////////////////////////////////////////
//
// QmlJSScriptConsoleWidget
//
///////////////////////////////////////////////////////////////////////
QmlJSScriptConsoleWidget::QmlJSScriptConsoleWidget(QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *vbox = new QVBoxLayout(this);
vbox->setMargin(0);
vbox->setSpacing(0);
QWidget *statusbarContainer = new QWidget;
QHBoxLayout *hbox = new QHBoxLayout(statusbarContainer);
hbox->setMargin(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
m_statusLabel = new Utils::StatusLabel;
hbox->addWidget(m_statusLabel, 20, Qt::AlignLeft);
hbox->addWidget(clearButton, 0, Qt::AlignRight);
m_console = new QmlJSScriptConsole;
connect(m_console, SIGNAL(evaluateExpression(QString)), this,
SIGNAL(evaluateExpression(QString)));
connect(m_console, SIGNAL(updateStatusMessage(const QString &, int)), m_statusLabel,
SLOT(showStatusMessage(const QString &, int)));
connect(clearAction, SIGNAL(triggered()), m_console, SLOT(clear()));
vbox->addWidget(statusbarContainer);
vbox->addWidget(m_console);
}
void QmlJSScriptConsoleWidget::setQmlAdapter(QmlAdapter *adapter)
{
m_console->setQmlAdapter(adapter);
}
void QmlJSScriptConsoleWidget::setInferiorStopped(bool inferiorStopped)
{
m_console->setInferiorStopped(inferiorStopped);
}
void QmlJSScriptConsoleWidget::appendResult(const QString &result)
{
m_console->appendResult(result);
}
///////////////////////////////////////////////////////////////////////
//
// QmlJSScriptConsole
//
///////////////////////////////////////////////////////////////////////
QmlJSScriptConsole::QmlJSScriptConsole(QWidget *parent)
: QPlainTextEdit(parent),
d(new QmlJSScriptConsolePrivate())
{
connect(this, SIGNAL(cursorPositionChanged()), SLOT(onCursorPositionChanged()));
setFrameStyle(QFrame::NoFrame);
setUndoRedoEnabled(false);
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::setQmlAdapter(QmlAdapter *adapter)
{
d->adapter = adapter;
clear();
}
void QmlJSScriptConsole::appendResult(const QString &result)
{
QString currentScript = getCurrentScript();
d->appendToHistory(currentScript);
QTextCursor cur = textCursor();
cur.movePosition(QTextCursor::EndOfLine);
cur.insertText(QLatin1String("\n"));
cur.insertText(result);
cur.movePosition(QTextCursor::EndOfLine);
cur.insertText(QLatin1String("\n"));
setTextCursor(cur);
displayPrompt();
QTextEdit::ExtraSelection sel;
QTextCharFormat resultFormat;
resultFormat.setForeground(QBrush(QColor(Qt::darkGray)));
QTextCursor c(document()->findBlockByNumber(cur.blockNumber()-1));
c.movePosition(QTextCursor::StartOfBlock);
c.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
sel.format = resultFormat;
sel.cursor = c;
d->selections.append(sel);
setExtraSelections(d->selections);
}
void QmlJSScriptConsole::clear()
{
d->resetCache();
QPlainTextEdit::clear();
displayPrompt();
}
void QmlJSScriptConsole::onStateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State state)
{
QDeclarativeDebugExpressionQuery *query = qobject_cast<QDeclarativeDebugExpressionQuery *>(sender());
bool gotResult = false;
if (query && state != QDeclarativeDebugQuery::Error) {
QString result(query->result().toString());
if (result != QLatin1String("<undefined>")) {
appendResult(result);
gotResult = true;
}
}
if (!gotResult) {
QString currentScript = getCurrentScript();
if (d->canEvaluateScript(currentScript)) {
emit evaluateExpression(currentScript);
} else {
QPlainTextEdit::appendPlainText(QLatin1String(""));
moveCursor(QTextCursor::EndOfLine);
}
}
delete query;
}
void QmlJSScriptConsole::onSelectionChanged()
{
if (!d->adapter.isNull()) {
QString status;
if (!d->inferiorStopped) {
status.append(tr("Current Selected Object: "));
status.append(d->adapter.data()->currentSelectedDisplayName());
}
emit updateStatusMessage(status, 0);
}
}
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;
}
case Qt::Key_Delete:
if (textCursor().selectionStart() < d->startOfEditableArea) {
keyConsumed = true;
}
break;
case Qt::Key_Tab:
case Qt::Key_Backtab:
keyConsumed = true;
break;
case Qt::Key_Left:
if (textCursor().position() == d->startOfEditableArea) {
keyConsumed = true;
} else if (e->modifiers() & Qt::ControlModifier && isEditableArea()) {
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;
}
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 evaluateScript = false;
//Check if string is only white spaces
if (currentScript.trimmed().isEmpty()) {
QTextCursor cur = textCursor();
cur.movePosition(QTextCursor::EndOfLine);
cur.insertText(QLatin1String("\n"));
setTextCursor(cur);
displayPrompt();
evaluateScript = true;
}
if (!evaluateScript && !d->inferiorStopped) {
if (!d->adapter.isNull()) {
QDeclarativeEngineDebug *engineDebug = d->adapter.data()->engineDebugClient();
int id = d->adapter.data()->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)));
evaluateScript = true;
}
}
}
if (!evaluateScript) {
if (d->canEvaluateScript(currentScript)) {
emit evaluateExpression(currentScript);
} else {
QPlainTextEdit::appendPlainText(QLatin1String(""));
moveCursor(QTextCursor::EndOfLine);
}
}
}
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::NextWord, 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::NextWord, QTextCursor::KeepAnchor)) ;
cursor.deleteChar();
cursor.insertText(script);
setTextCursor(cursor);
}
bool QmlJSScriptConsole::isEditableArea() const
{
return textCursor().position() >= d->startOfEditableArea;
}
} //Internal
} //Debugger

View File

@@ -0,0 +1,130 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.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 info@qt.nokia.com.
**
**************************************************************************/
#ifndef QMLJSSCRIPTCONSOLE_H
#define QMLJSSCRIPTCONSOLE_H
#include <qmljsdebugclient/qdeclarativeenginedebug.h>
#include <QtGui/QPlainTextEdit>
namespace Utils {
class StatusLabel;
}
namespace Debugger {
class QmlAdapter;
namespace Internal {
class QmlJSScriptConsolePrivate;
class QmlJSScriptConsole;
class QmlJSScriptConsoleWidget : public QWidget
{
Q_OBJECT
public:
QmlJSScriptConsoleWidget(QWidget *parent = 0);
void setQmlAdapter(QmlAdapter *adapter);
void setInferiorStopped(bool inferiorStopped);
public slots:
void appendResult(const QString &result);
signals:
void evaluateExpression(const QString &expr);
private:
QmlJSScriptConsole *m_console;
Utils::StatusLabel *m_statusLabel;
};
class QmlJSScriptConsole : public QPlainTextEdit
{
Q_OBJECT
public:
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 setQmlAdapter(QmlAdapter *adapter);
void appendResult(const QString &result);
public slots:
void clear();
void onStateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State);
void onSelectionChanged();
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 onCursorPositionChanged();
private:
void displayPrompt();
void handleReturnKey();
void handleUpKey();
void handleDownKey();
void handleHomeKey();
QString getCurrentScript() const;
void replaceCurrentScript(const QString &script);
bool isEditableArea() const;
private:
QmlJSScriptConsolePrivate *d;
};
} //Internal
} //Debugger
#endif

View File

@@ -1,241 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.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 info@qt.nokia.com.
**
**************************************************************************/
#include "scriptconsole.h"
#include <QtCore/QDebug>
#include <QtGui/QVBoxLayout>
#include <QtGui/QDockWidget>
#include <qmljseditor/qmljshighlighter.h>
#include <utils/styledbar.h>
#include <utils/filterlineedit.h>
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorconstants.h>
#include <texteditor/texteditorsettings.h>
namespace Debugger {
namespace Internal {
ScriptConsole::ScriptConsole(QWidget *parent)
: QWidget(parent),
m_textEdit(new QPlainTextEdit),
m_lineEdit(0)
{
// m_prompt = QLatin1String(">");
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setMargin(0);
layout->setSpacing(0);
layout->addWidget(m_textEdit);
m_textEdit->setFrameStyle(QFrame::NoFrame);
//updateTitle();
/*m_highlighter = new QmlJSEditor::Highlighter(m_textEdit->document());
m_highlighter->setParent(m_textEdit->document());*/
Utils::StyledBar *bar = new Utils::StyledBar;
m_lineEdit = new Utils::FilterLineEdit;
m_lineEdit->setPlaceholderText(tr("<Type expression to evaluate>"));
m_lineEdit->setToolTip(tr("Write and evaluate QtScript expressions."));
/*m_clearButton = new QToolButton();
m_clearButton->setToolTip(tr("Clear Output"));
m_clearButton->setIcon(QIcon(Core::Constants::ICON_CLEAN_PANE));
connect(m_clearButton, SIGNAL(clicked()), this, SLOT(clearTextEditor()));*/
//connect(m_lineEdit, SIGNAL(textChanged(QString)), SLOT(changeContextHelpId(QString)));
connect(m_lineEdit, SIGNAL(returnPressed()), SLOT(executeExpression()));
QHBoxLayout *hbox = new QHBoxLayout(bar);
hbox->setMargin(1);
hbox->setSpacing(1);
hbox->addWidget(m_lineEdit);
//hbox->addWidget(m_clearButton);
layout->addWidget(bar);
m_textEdit->setReadOnly(true);
m_lineEdit->installEventFilter(this);
setFontSettings();
}
void ScriptConsole::setFontSettings()
{
const TextEditor::FontSettings &fs = TextEditor::TextEditorSettings::instance()->fontSettings();
static QVector<QString> categories;
if (categories.isEmpty()) {
categories << QLatin1String(TextEditor::Constants::C_NUMBER)
<< QLatin1String(TextEditor::Constants::C_STRING)
<< QLatin1String(TextEditor::Constants::C_TYPE)
<< QLatin1String(TextEditor::Constants::C_KEYWORD)
<< QLatin1String(TextEditor::Constants::C_LABEL)
<< QLatin1String(TextEditor::Constants::C_COMMENT)
<< QLatin1String(TextEditor::Constants::C_VISUAL_WHITESPACE);
}
const QVector<QTextCharFormat> formats = fs.toTextCharFormats(categories);
/* m_highlighter->setFormats(formats);
m_highlighter->rehighlight();*/
m_textEdit->setFont(fs.font());
m_lineEdit->setFont(fs.font());
}
void ScriptConsole::clear()
{
clearTextEditor();
if (m_lineEdit)
m_lineEdit->clear();
// appendPrompt();
}
void ScriptConsole::clearTextEditor()
{
m_textEdit->clear();
m_textEdit->appendPlainText(tr("Script Console\n"));
}
/*void ExpressionQueryWidget::updateTitle()
{
if (m_currObject.debugId() < 0) {
m_title = tr("Expression queries");
} else {
QString desc = QLatin1String("<")
+ m_currObject.className() + QLatin1String(": ")
+ (m_currObject.name().isEmpty() ? QLatin1String("<unnamed>") : m_currObject.name())
+ QLatin1String(">");
m_title = tr("Expression queries (using context for %1)" , "Selected object").arg(desc);
}
}*/
/*
void ExpressionQueryWidget::appendPrompt()
{
m_textEdit->moveCursor(QTextCursor::End);
if (m_mode == SeparateEntryMode) {
m_textEdit->insertPlainText("\n");
} else {
m_textEdit->appendPlainText(m_prompt);
}
}
*/
bool ScriptConsole::eventFilter(QObject* obj, QEvent* event)
{
if (obj == m_textEdit) {
switch (event->type()) {
case QEvent::KeyPress:
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
int key = keyEvent->key();
if (key == Qt::Key_Return || key == Qt::Key_Enter) {
executeExpression();
return true;
} else if (key == Qt::Key_Backspace) {
// ensure m_expr doesn't contain backspace characters
QTextCursor cursor = m_textEdit->textCursor();
bool atLastLine = !(cursor.block().next().isValid());
if (!atLastLine)
return true;
if (cursor.positionInBlock() <= m_prompt.count())
return true;
cursor.deletePreviousChar();
m_expr = cursor.block().text().mid(m_prompt.count());
return true;
} else {
m_textEdit->moveCursor(QTextCursor::End);
m_expr += keyEvent->text();
}
break;
}
case QEvent::FocusIn:
//checkCurrentContext();
m_textEdit->moveCursor(QTextCursor::End);
break;
default:
break;
}
} else if (obj == m_lineEdit) {
switch (event->type()) {
case QEvent::KeyPress:
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
int key = keyEvent->key();
if (key == Qt::Key_Up && m_lineEdit->text() != m_lastExpr) {
m_expr = m_lineEdit->text();
if (!m_lastExpr.isEmpty())
m_lineEdit->setText(m_lastExpr);
} else if (key == Qt::Key_Down) {
m_lineEdit->setText(m_expr);
}
break;
}
case QEvent::FocusIn:
// checkCurrentContext();
break;
default:
break;
}
}
return QWidget::eventFilter(obj, event);
}
void ScriptConsole::executeExpression()
{
m_expr = m_lineEdit->text().trimmed();
m_expr = m_expr.trimmed();
if (!m_expr.isEmpty()) {
emit expressionEntered(m_expr);
m_lastExpr = m_expr;
if (m_lineEdit)
m_lineEdit->clear();
}
}
void ScriptConsole::appendResult(const QString& result)
{
m_textEdit->moveCursor(QTextCursor::End);
m_textEdit->insertPlainText(m_expr + " : ");
m_textEdit->insertPlainText(result);
m_textEdit->insertPlainText("\n");
m_expr.clear();
}
}
}

View File

@@ -63,6 +63,12 @@ ClientProxy::ClientProxy(Debugger::QmlAdapter *adapter, QObject *parent)
connectToServer();
}
ClientProxy::~ClientProxy()
{
m_adapter.data()->setEngineDebugClient(0);
m_adapter.data()->setCurrentSelectedDebugInfo(-1);
}
void ClientProxy::connectToServer()
{
m_engineClient = new QDeclarativeEngineDebug(m_adapter.data()->connection(), this);
@@ -70,6 +76,8 @@ void ClientProxy::connectToServer()
connect(m_engineClient, SIGNAL(newObjects()), this, SLOT(newObjects()));
connect(m_engineClient, SIGNAL(statusChanged(QDeclarativeDebugClient::Status)),
this, SLOT(clientStatusChanged(QDeclarativeDebugClient::Status)));
connect(m_engineClient, SIGNAL(statusChanged(QDeclarativeDebugClient::Status)),
this, SLOT(engineClientStatusChanged(QDeclarativeDebugClient::Status)));
m_inspectorClient = new QmlJSInspectorClient(m_adapter.data()->connection(), this);
@@ -116,6 +124,13 @@ void ClientProxy::clientStatusChanged(QDeclarativeDebugClient::Status status)
updateConnected();
}
void ClientProxy::engineClientStatusChanged(QDeclarativeDebugClient::Status status)
{
if (status == QDeclarativeDebugClient::Enabled) {
m_adapter.data()->setEngineDebugClient(qobject_cast<QDeclarativeEngineDebug *>(sender()));
}
}
void ClientProxy::refreshObjectTree()
{
if (!m_contextQuery) {
@@ -434,7 +449,7 @@ void ClientProxy::queryEngineContext(int id)
if (!m_contextQuery->isWaiting())
contextChanged();
else
connect(m_contextQuery, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
connect(m_contextQuery, SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)),
this, SLOT(contextChanged()));
}
@@ -471,8 +486,8 @@ void ClientProxy::fetchContextObjectRecursive(const QDeclarativeDebugContextRefe
} else {
m_objectTreeQuery << query;
connect(query,
SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
SLOT(objectTreeFetched(QDeclarativeDebugQuery::State)));
SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)),
SLOT(objectTreeFetched(QmlJsDebugClient::QDeclarativeDebugQuery::State)));
}
}
foreach (const QDeclarativeDebugContextReference& child, context.contexts()) {
@@ -481,7 +496,7 @@ void ClientProxy::fetchContextObjectRecursive(const QDeclarativeDebugContextRefe
}
void ClientProxy::objectTreeFetched(QDeclarativeDebugQuery::State state)
void ClientProxy::objectTreeFetched(QmlJsDebugClient::QDeclarativeDebugQuery::State state)
{
QDeclarativeDebugObjectQuery *query = qobject_cast<QDeclarativeDebugObjectQuery *>(sender());
if (!query || state == QDeclarativeDebugQuery::Error) {
@@ -646,7 +661,7 @@ void ClientProxy::reloadEngines()
if (!m_engineQuery->isWaiting()) {
updateEngineList();
} else {
connect(m_engineQuery, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
connect(m_engineQuery, SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)),
this, SLOT(updateEngineList()));
}
}

View File

@@ -58,6 +58,7 @@ class ClientProxy : public QObject
public:
explicit ClientProxy(Debugger::QmlAdapter *adapter, QObject *parent = 0);
~ClientProxy();
bool setBindingForObject(int objectDebugId,
const QString &propertyName,
@@ -137,12 +138,13 @@ public slots:
private slots:
void connectToServer();
void clientStatusChanged(QDeclarativeDebugClient::Status status);
void engineClientStatusChanged(QDeclarativeDebugClient::Status status);
void contextChanged();
void onCurrentObjectsChanged(const QList<int> &debugIds, bool requestIfNeeded = true);
void updateEngineList();
void objectTreeFetched(QDeclarativeDebugQuery::State state = QDeclarativeDebugQuery::Completed);
void objectTreeFetched(QmlJsDebugClient::QDeclarativeDebugQuery::State state = QmlJsDebugClient::QDeclarativeDebugQuery::Completed);
void fetchContextObjectRecursive(const QmlJsDebugClient::QDeclarativeDebugContextReference& context);
void newObjects();
void objectWatchTriggered(const QByteArray &propertyName, const QVariant &propertyValue);

View File

@@ -48,6 +48,7 @@
#include <debugger/debuggerconstants.h>
#include <debugger/debuggermainwindow.h>
#include <debugger/debuggerplugin.h>
#include <debugger/qml/qmladapter.h>
#include <utils/filterlineedit.h>
#include <utils/qtcassert.h>
@@ -272,13 +273,13 @@ void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextE
if (!query.isEmpty()) {
m_debugQuery = m_clientProxy->queryExpressionResult(ref.debugId(), query);
connect(m_debugQuery, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
this, SLOT(debugQueryUpdated(QDeclarativeDebugQuery::State)));
connect(m_debugQuery, SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)),
this, SLOT(debugQueryUpdated(QmlJsDebugClient::QDeclarativeDebugQuery::State)));
}
}
}
void InspectorUi::debugQueryUpdated(QDeclarativeDebugQuery::State newState)
void InspectorUi::debugQueryUpdated(QmlJsDebugClient::QDeclarativeDebugQuery::State newState)
{
if (newState != QDeclarativeDebugExpressionQuery::Completed)
return;
@@ -289,8 +290,8 @@ void InspectorUi::debugQueryUpdated(QDeclarativeDebugQuery::State newState)
if (!text.isEmpty())
QToolTip::showText(QCursor::pos(), text);
disconnect(m_debugQuery, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
this, SLOT(debugQueryUpdated(QDeclarativeDebugQuery::State)));
disconnect(m_debugQuery, SIGNAL(stateChanged(QmlJsDebugClient::QDeclarativeDebugQuery::State)),
this, SLOT(debugQueryUpdated(QmlJsDebugClient::QDeclarativeDebugQuery::State)));
}
bool InspectorUi::isConnected() const
@@ -525,24 +526,6 @@ inline QDeclarativeDebugObjectReference findParentRecursive( int goalDebugId,
return QDeclarativeDebugObjectReference();
}
void InspectorUi::selectItems(const QList<QDeclarativeDebugObjectReference> &objectReferences)
{
foreach (const QDeclarativeDebugObjectReference &objref, objectReferences) {
if (objref.debugId() != -1) {
// select only the first valid element of the list
m_clientProxy->removeAllObjectWatches();
m_clientProxy->addObjectWatch(objref.debugId());
QList <QDeclarativeDebugObjectReference> selectionList;
selectionList << objref;
m_propertyInspector->setCurrentObjects(selectionList);
populateCrumblePath(objref);
gotoObjectReferenceDefinition(objref);
return;
}
}
}
inline QString displayName(const QDeclarativeDebugObjectReference &obj)
{
// special! state names
@@ -566,6 +549,26 @@ inline QString displayName(const QDeclarativeDebugObjectReference &obj)
return QString("<%1>").arg(objTypeName);
}
void InspectorUi::selectItems(const QList<QDeclarativeDebugObjectReference> &objectReferences)
{
foreach (const QDeclarativeDebugObjectReference &objref, objectReferences) {
int debugId = objref.debugId();
if (debugId != -1) {
// select only the first valid element of the list
m_clientProxy->removeAllObjectWatches();
m_clientProxy->addObjectWatch(debugId);
QList <QDeclarativeDebugObjectReference> selectionList;
selectionList << objref;
m_propertyInspector->setCurrentObjects(selectionList);
populateCrumblePath(objref);
gotoObjectReferenceDefinition(objref);
m_clientProxy->qmlAdapter()->setCurrentSelectedDebugInfo(debugId, displayName(objref));
break;
}
}
}
bool InspectorUi::isRoot(const QDeclarativeDebugObjectReference &obj) const
{
foreach (const QDeclarativeDebugObjectReference &rootObj, m_clientProxy->rootObjectReference())

View File

@@ -133,7 +133,7 @@ private slots:
void updatePendingPreviewDocuments(QmlJS::Document::Ptr doc);
void showDebuggerTooltip(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
void debugQueryUpdated(QDeclarativeDebugQuery::State);
void debugQueryUpdated(QmlJsDebugClient::QDeclarativeDebugQuery::State);
private:
bool addQuotesForData(const QVariant &value) const;