Commit dbcaadd8 authored by Oswald Buddenhagen's avatar Oswald Buddenhagen
Browse files

Merge remote-tracking branch 'origin/2.5'

Conflicts:
	src/plugins/debugger/qml/qmlengine.cpp
	src/plugins/qtsupport/gettingstartedwelcomepage.cpp

Change-Id: I9157b9b9c05564ddeb3c72cec6b59523b8165d76
parents e01e8997 b9dfbd8e
......@@ -1060,9 +1060,15 @@ void QmlEngine::expressionEvaluated(quint32 queryId, const QVariant &result)
{
if (d->queryIds.contains(queryId)) {
d->queryIds.removeOne(queryId);
QtMessageLogItem *item = constructLogItemTree(result);
QtMessageLogItem *item = constructLogItemTree(qtMessageLogHandler()->root(),
result);
if (item)
qtMessageLogHandler()->appendItem(item);
} else {
qtMessageLogHandler()->
appendItem(new QtMessageLogItem(qtMessageLogHandler()->root(),
QtMessageLogHandler::ErrorType,
_("Error evaluating expression.")));
}
}
......@@ -1133,7 +1139,8 @@ void QmlEngine::appendDebugOutput(QtMsgType type, const QString &message,
//This case is not possible
return;
}
QtMessageLogItem *item = new QtMessageLogItem(itemType, message);
QtMessageLogItem *item = new QtMessageLogItem(qtMessageLogHandler()->root(),
itemType, message);
item->file = info.file;
item->line = info.line;
qtMessageLogHandler()->appendItem(item);
......@@ -1175,6 +1182,7 @@ bool QmlEngine::evaluateScriptExpression(const QString& expression)
qtMessageLogHandler()->
appendItem(
new QtMessageLogItem(
qtMessageLogHandler()->root(),
QtMessageLogHandler::ErrorType,
_("Error evaluating expression.")));
}
......@@ -1189,8 +1197,9 @@ bool QmlEngine::evaluateScriptExpression(const QString& expression)
//Incase of invalid context, show Error message
qtMessageLogHandler()->
appendItem(new QtMessageLogItem(
qtMessageLogHandler()->root(),
QtMessageLogHandler::ErrorType,
_("Cannot evaluate without"
_("Cannot evaluate without "
"a valid QML/JS Context.")),
qtMessageLogHandler()->rowCount());
}
......@@ -1301,12 +1310,12 @@ bool QmlEngine::canEvaluateScript(const QString &script)
}
QtMessageLogItem *QmlEngine::constructLogItemTree(
const QVariant &result, const QString &key)
QtMessageLogItem *parent, const QVariant &result, const QString &key)
{
if (!result.isValid())
return 0;
QtMessageLogItem *item = new QtMessageLogItem();
QtMessageLogItem *item = new QtMessageLogItem(parent);
if (result.type() == QVariant::Map) {
if (key.isEmpty())
item->text = _("Object");
......@@ -1316,9 +1325,10 @@ QtMessageLogItem *QmlEngine::constructLogItemTree(
QMapIterator<QString, QVariant> i(result.toMap());
while (i.hasNext()) {
i.next();
QtMessageLogItem *child = constructLogItemTree(i.value(), i.key());
QtMessageLogItem *child = constructLogItemTree(item,
i.value(), i.key());
if (child)
item->insertChild(item->childCount(), child);
item->insertChild(child);
}
} else if (result.type() == QVariant::List) {
if (key.isEmpty())
......@@ -1327,10 +1337,10 @@ QtMessageLogItem *QmlEngine::constructLogItemTree(
item->text = QString(_("[%1] : List")).arg(key);
QVariantList resultList = result.toList();
for (int i = 0; i < resultList.count(); i++) {
QtMessageLogItem *child = constructLogItemTree(resultList.at(i),
QtMessageLogItem *child = constructLogItemTree(item, resultList.at(i),
QString::number(i));
if (child)
item->insertChild(item->childCount(), child);
item->insertChild(child);
}
} else if (result.canConvert(QVariant::String)) {
item->text = result.toString();
......
......@@ -185,7 +185,8 @@ private:
void updateEditor(Core::IEditor *editor, const QTextDocument *document);
bool canEvaluateScript(const QString &script);
QtMessageLogItem *constructLogItemTree(const QVariant &result,
QtMessageLogItem *constructLogItemTree(QtMessageLogItem *parent,
const QVariant &result,
const QString &key = QString());
bool adjustBreakpointLineAndColumn(const QString &filePath, quint32 *line,
quint32 *column, bool *valid);
......
......@@ -128,8 +128,8 @@ public:
//TODO:: remove this method
void reformatRequest(QByteArray &request);
QtMessageLogItem *constructLogItemTree(const QmlV8ObjectData &objectData,
const QVariant &refsVal);
QtMessageLogItem *constructLogItemTree(QtMessageLogItem *parent,
const QmlV8ObjectData &objectData, const QVariant &refsVal);
private:
QByteArray packMessage(const QByteArray &type, const QByteArray &message = QByteArray());
QScriptValue initObject();
......@@ -150,6 +150,8 @@ public:
QHash<int, QString> evaluatingExpression;
QHash<int, QByteArray> localsAndWatchers;
QList<int> updateLocalsAndWatchers;
QList<int> debuggerCommands;
//Cache
QStringList watchedExpressions;
......@@ -831,6 +833,7 @@ QmlV8ObjectData QmlV8DebuggerClientPrivate::extractData(const QVariant &data,
objectData.properties = data.properties;
}
} else {
objectData.handle = dataMap.value(_(HANDLE)).toInt();
QString type = dataMap.value(_(TYPE)).toString();
if (type == _("undefined")) {
......@@ -876,6 +879,8 @@ void QmlV8DebuggerClientPrivate::clearCache()
{
watchedExpressions.clear();
currentFrameScopes.clear();
evaluatingExpression.clear();
updateLocalsAndWatchers.clear();
}
QByteArray QmlV8DebuggerClientPrivate::packMessage(const QByteArray &type, const QByteArray &message)
......@@ -969,6 +974,7 @@ void QmlV8DebuggerClientPrivate::reformatRequest(QByteArray &request)
}
QtMessageLogItem *QmlV8DebuggerClientPrivate::constructLogItemTree(
QtMessageLogItem *parent,
const QmlV8ObjectData &objectData,
const QVariant &refsVal)
{
......@@ -982,14 +988,14 @@ QtMessageLogItem *QmlV8DebuggerClientPrivate::constructLogItemTree(
text = QString(_("%1: %2")).arg(QString::fromAscii(objectData.name))
.arg(objectData.value.toString());
QtMessageLogItem *item = new QtMessageLogItem(
QtMessageLogHandler::UndefinedType, text);
QtMessageLogItem *item = new QtMessageLogItem(parent,
QtMessageLogHandler::UndefinedType, text);
foreach (const QVariant &property, objectData.properties) {
QtMessageLogItem *child = constructLogItemTree(
extractData(property, refsVal), refsVal);
item, extractData(property, refsVal), refsVal);
if (child)
item->insertChild(item->childCount(), child);
item->insertChild(child);
}
return item;
......@@ -1161,6 +1167,7 @@ void QmlV8DebuggerClient::assignValueInDebugger(const WatchData * /*data*/,
QString expression = QString(_("%1 = %2;")).arg(expr).arg(valueV.toString());
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
d->evaluate(expression, false, false, stackHandler->currentIndex());
d->updateLocalsAndWatchers.append(d->sequence);
} else {
d->engine->showMessage(QString(_("Cannot evaluate"
"%1 in current stack frame")).
......@@ -1178,7 +1185,7 @@ void QmlV8DebuggerClient::executeDebuggerCommand(const QString &command)
StackHandler *stackHandler = d->engine->stackHandler();
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
d->evaluate(command, false, false, stackHandler->currentIndex());
d->evaluatingExpression.insert(d->sequence, command);
d->debuggerCommands.append(d->sequence);
} else {
//Currently cannot evaluate if not in a javascript break
d->engine->showMessage(QString(_("Cannot evaluate %1"
......@@ -1192,7 +1199,6 @@ void QmlV8DebuggerClient::synchronizeWatchers(const QStringList &watchers)
SDEBUG(watchers);
foreach (const QString &exp, watchers) {
if (!d->watchedExpressions.contains(exp)) {
d->watchedExpressions << exp;
StackHandler *stackHandler = d->engine->stackHandler();
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
d->evaluate(exp, false, false, stackHandler->currentIndex());
......@@ -1200,11 +1206,24 @@ void QmlV8DebuggerClient::synchronizeWatchers(const QStringList &watchers)
}
}
}
d->watchedExpressions = watchers;
}
void QmlV8DebuggerClient::expandObject(const QByteArray &iname, quint64 objectId)
{
d->localsAndWatchers.insert(objectId, iname);
if (objectId == 0) {
//We may have got the global object
const WatchData *watch = d->engine->watchHandler()->findItem(iname);
if (watch->value == QLatin1String("global")) {
StackHandler *stackHandler = d->engine->stackHandler();
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
d->evaluate(watch->name, false, false, stackHandler->currentIndex());
d->evaluatingExpression.insert(d->sequence, QLatin1String(iname));
}
return;
}
}
d->localsAndWatchers.insertMulti(objectId, iname);
d->lookup(QList<int>() << objectId);
}
......@@ -1702,6 +1721,12 @@ void QmlV8DebuggerClient::setCurrentFrameDetails(const QVariant &bodyVal, const
data.type = objectData.type;
data.value = objectData.value.toString();
data.setHasChildren(objectData.properties.count());
//Incase of global object, we do not get children
//Set children nevertheless and query later
if (data.value == QLatin1String("global")) {
data.setHasChildren(true);
data.id = 0;
}
d->engine->watchHandler()->beginCycle();
d->engine->watchHandler()->insertData(data);
d->engine->watchHandler()->endCycle();
......@@ -1774,7 +1799,7 @@ void QmlV8DebuggerClient::updateScope(const QVariant &bodyVal, const QVariant &r
locals << data;
} else {
handlesToLookup << handle;
d->localsAndWatchers.insert(handle, data.exp);
d->localsAndWatchers.insertMulti(handle, data.exp);
}
}
......@@ -1799,43 +1824,60 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con
// "running" : <is the VM running after sending this response>
// "success" : true
// }
if (!d->evaluatingExpression.contains(sequence)) {
if (d->updateLocalsAndWatchers.contains(sequence)) {
d->updateLocalsAndWatchers.removeOne(sequence);
//Update the locals
foreach (int index, d->currentFrameScopes)
d->scope(index);
//Also update "this"
QByteArray iname("local.this");
const WatchData *parent = d->engine->watchHandler()->findItem(iname);
d->localsAndWatchers.insertMulti(parent->id, iname);
d->lookup(QList<int>() << parent->id);
} else if (d->debuggerCommands.contains(sequence)) {
d->updateLocalsAndWatchers.removeOne(sequence);
QmlV8ObjectData body = d->extractData(bodyVal, refsVal);
QtMessageLogItem *item = d->constructLogItemTree(d->engine->qtMessageLogHandler()->root(),
body, refsVal);
if (item)
d->engine->qtMessageLogHandler()->appendItem(item);
//Update the locals
foreach (int index, d->currentFrameScopes)
d->scope(index);
} else {
QmlV8ObjectData body = d->extractData(bodyVal, refsVal);
QString exp = d->evaluatingExpression.take(sequence);
if (d->watchedExpressions.contains(exp)) {
QByteArray iname = d->engine->watchHandler()->watcherName(exp.toLatin1());
SDEBUG(QString(iname));
if (d->evaluatingExpression.contains(sequence)) {
QString exp = d->evaluatingExpression.take(sequence);
QList<WatchData> watchDataList;
WatchData data;
data.exp = exp.toLatin1();
data.name = exp;
data.iname = iname;
data.id = body.handle;
if (success) {
data.type = body.type;
data.value = body.value.toString();
data.hasChildren = body.properties.count();
//Do we have request to evaluate a local?
if (exp.startsWith("local.")) {
const WatchData *watch = d->engine->watchHandler()->findItem(exp.toLatin1());
watchDataList << createWatchDataList(watch, body.properties, refsVal);
} else {
//Do not set type since it is unknown
data.setError(body.value.toString());
QByteArray iname = d->engine->watchHandler()->watcherName(exp.toLatin1());
SDEBUG(QString(iname));
data.exp = exp.toLatin1();
data.name = exp;
data.iname = iname;
data.id = body.handle;
if (success) {
data.type = body.type;
data.value = body.value.toString();
data.hasChildren = body.properties.count();
} else {
//Do not set type since it is unknown
data.setError(body.value.toString());
}
watchDataList << data << createWatchDataList(&data, body.properties, refsVal);
}
//Insert the newly evaluated expression to the Watchers Window
d->engine->watchHandler()->beginCycle(false);
d->engine->watchHandler()->insertData(data);
d->engine->watchHandler()->insertBulkData(watchDataList);
d->engine->watchHandler()->endCycle();
} else {
QtMessageLogItem *item = d->constructLogItemTree(body, refsVal);
if (item)
d->engine->qtMessageLogHandler()->appendItem(item);
//Update the locals
foreach (int index, d->currentFrameScopes)
d->scope(index);
}
}
}
......@@ -1911,35 +1953,9 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const
if (prepend.startsWith("local.") || prepend.startsWith("watch.")) {
//Data for expanded local/watch
if (bodyObjectData.properties.count()) {
//Could be an object or function
const WatchData *parent = d->engine->watchHandler()->findItem(prepend);
foreach (const QVariant &property, bodyObjectData.properties) {
QmlV8ObjectData propertyData = d->extractData(property, refsVal);
WatchData data;
data.name = propertyData.name;
//Check for v8 specific local data
if (data.name.startsWith(QLatin1Char('.')) || data.name.isEmpty())
continue;
if (parent && parent->type == "object") {
if (parent->value == _("Array"))
data.exp = parent->exp + QByteArray("[") +
data.name.toLatin1() + QByteArray("]");
else if (parent->value == _("Object"))
data.exp = parent->exp + QByteArray(".") + data.name.toLatin1();
} else {
data.exp = data.name.toLatin1();
}
data.iname = prepend + '.' + data.name.toLatin1();
data.id = propertyData.handle;
data.type = propertyData.type;
data.value = propertyData.value.toString();
data.setHasChildren(propertyData.properties.count());
watchDataList << data;
}
}
//Could be an object or function
const WatchData *parent = d->engine->watchHandler()->findItem(prepend);
watchDataList << createWatchDataList(parent, bodyObjectData.properties, refsVal);
} else {
//rest
WatchData data;
......@@ -1962,6 +1978,41 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const
d->engine->watchHandler()->endCycle();
}
QList<WatchData> QmlV8DebuggerClient::createWatchDataList(const WatchData *parent,
const QVariantList &properties,
const QVariant &refsVal)
{
QList<WatchData> watchDataList;
if (properties.count()) {
QTC_ASSERT(parent, return watchDataList);
foreach (const QVariant &property, properties) {
QmlV8ObjectData propertyData = d->extractData(property, refsVal);
WatchData data;
data.name = propertyData.name;
//Check for v8 specific local data
if (data.name.startsWith(QLatin1Char('.')) || data.name.isEmpty())
continue;
if (parent->type == "object") {
if (parent->value == _("Array"))
data.exp = parent->exp + '[' + data.name.toLatin1() + ']';
else if (parent->value == _("Object"))
data.exp = parent->exp + '.' + data.name.toLatin1();
} else {
data.exp = data.name.toLatin1();
}
data.iname = parent->iname + '.' + data.name.toLatin1();
data.id = propertyData.handle;
data.type = propertyData.type;
data.value = propertyData.value.toString();
data.setHasChildren(propertyData.properties.count());
watchDataList << data;
}
}
return watchDataList;
}
void QmlV8DebuggerClient::highlightExceptionCode(int lineNumber,
const QString &filePath,
const QString &errorMessage)
......
......@@ -116,6 +116,9 @@ private:
void updateBreakpoints(const QVariant &bodyVal);
void expandLocalsAndWatchers(const QVariant &bodyVal, const QVariant &refsVal);
QList<WatchData> createWatchDataList(const WatchData *parent,
const QVariantList &properties,
const QVariant &refsVal);
void highlightExceptionCode(int lineNumber, const QString &filePath,
const QString &errorMessage);
......
......@@ -31,6 +31,8 @@
**************************************************************************/
#include "qtmessageloghandler.h"
#include "debuggercore.h"
#include "debuggeractions.h"
#include <utils/qtcassert.h>
......@@ -45,8 +47,8 @@ namespace Internal {
//
///////////////////////////////////////////////////////////////////////
QtMessageLogItem::QtMessageLogItem(QtMessageLogHandler::ItemType itemType,
const QString &text, QtMessageLogItem *parent)
QtMessageLogItem::QtMessageLogItem(QtMessageLogItem *parent,
QtMessageLogHandler::ItemType itemType, const QString &text)
: m_parentItem(parent),
text(text),
itemType(itemType),
......@@ -86,23 +88,35 @@ bool QtMessageLogItem::insertChildren(int position, int count)
for (int row = 0; row < count; ++row) {
QtMessageLogItem *item = new
QtMessageLogItem(QtMessageLogHandler::UndefinedType, QString(),
this);
QtMessageLogItem(this , QtMessageLogHandler::UndefinedType,
QString());
m_childItems.insert(position, item);
}
return true;
}
void QtMessageLogItem::insertChild(QtMessageLogItem *item)
{
if (!debuggerCore()->boolSetting(SortStructMembers)) {
m_childItems.insert(m_childItems.count(), item);
return;
}
int i = 0;
for (; i < m_childItems.count(); i++) {
if (item->text < m_childItems[i]->text) {
break;
}
}
m_childItems.insert(i, item);
}
bool QtMessageLogItem::insertChild(int position, QtMessageLogItem *item)
{
if (position < 0 || position > m_childItems.size())
return false;
if (item->parent())
item->parent()->detachChild(item->childNumber());
item->m_parentItem = this;
m_childItems.insert(position, item);
return true;
......@@ -143,7 +157,7 @@ bool QtMessageLogItem::detachChild(int position)
QtMessageLogHandler::QtMessageLogHandler(QObject *parent) :
QAbstractItemModel(parent),
m_hasEditableRow(false),
m_rootItem(new QtMessageLogItem()),
m_rootItem(new QtMessageLogItem(0)),
m_maxSizeOfFileName(0)
{
}
......@@ -157,8 +171,8 @@ void QtMessageLogHandler::clear()
{
beginResetModel();
reset();
delete m_rootItem;
m_rootItem = new QtMessageLogItem();
qDeleteAll(m_rootItem->m_childItems);
m_rootItem->m_childItems.clear();
endResetModel();
if (m_hasEditableRow)
......@@ -180,7 +194,7 @@ bool QtMessageLogHandler::appendItem(QtMessageLogItem *item, int position)
bool QtMessageLogHandler::appendMessage(QtMessageLogHandler::ItemType itemType,
const QString &message, int position)
{
return appendItem(new QtMessageLogItem(itemType, message), position);
return appendItem(new QtMessageLogItem(m_rootItem, itemType, message), position);
}
void QtMessageLogHandler::setHasEditableRow(bool hasEditableRow)
......@@ -202,7 +216,7 @@ bool QtMessageLogHandler::hasEditableRow() const
void QtMessageLogHandler::appendEditableRow()
{
int position = m_rootItem->childCount();
if (appendItem(new QtMessageLogItem(QtMessageLogHandler::InputType), position))
if (appendItem(new QtMessageLogItem(m_rootItem, QtMessageLogHandler::InputType), position))
emit selectEditableRow(index(position, 0),
QItemSelectionModel::ClearAndSelect);
}
......@@ -289,7 +303,8 @@ QModelIndex QtMessageLogHandler::parent(const QModelIndex &index) const
return QModelIndex();
//can parentItem be 0?
QTC_ASSERT(parentItem, qDebug("Parent is Null!!"));
if (!parentItem)
return QModelIndex();
return createIndex(parentItem->childNumber(), 0, parentItem);
}
......
......@@ -78,6 +78,8 @@ public:
int sizeOfFile(const QFont &font);
int sizeOfLineNumber(const QFont &font);
QtMessageLogItem *root() const { return m_rootItem; }
public slots:
void clear();
......@@ -116,14 +118,15 @@ private:
class QtMessageLogItem
{
public:
QtMessageLogItem(QtMessageLogHandler::ItemType type = QtMessageLogHandler::UndefinedType,
const QString &data = QString(),
QtMessageLogItem *parent = 0);
QtMessageLogItem(QtMessageLogItem *parent,
QtMessageLogHandler::ItemType type = QtMessageLogHandler::UndefinedType,
const QString &data = QString());
~QtMessageLogItem();
QtMessageLogItem *child(int number);
int childCount() const;
bool insertChildren(int position, int count);
void insertChild(QtMessageLogItem *item);
bool insertChild(int position, QtMessageLogItem *item);
QtMessageLogItem *parent();
bool removeChildren(int position, int count);
......@@ -139,6 +142,9 @@ public:
QtMessageLogHandler::ItemType itemType;
QString file;
int line;
private:
friend class QtMessageLogHandler;
};
} //Internal
......
......@@ -2013,7 +2013,7 @@ namespace final {
BREAK_HERE;
// Expand settings.
// Check settings "" QSettings.
// Check settings.[QObject] "" QSettings.
// Check settings.@1 "" QObject.
// Check value "" QVariant (QString).
// Continue.
dummyStatement(&settings, &value);
......@@ -3577,7 +3577,7 @@ namespace qthread {
// Expand this.
// Check j 3 int.
// CheckType this qthread::Thread.
// Check this.[QThread] "This is thread #3" qthread::Thread.
// Check this.@1 "This is thread #3" QThread.
// Continue.
dummyStatement(this);
}
......@@ -3767,7 +3767,8 @@ namespace qvariant {
// Check ha1.isParsed false bool.
// Check ha1.protocol QAbstractSocket::UnknownNetworkLayerProtocol (-1) QAbstractSocket::NetworkLayerProtocol.
// Check ha1.scopeId "" QString.
// Check var "127.0.0.1" QVariant (QHostAddress).
// CheckType var QVariant (QHostAddress).
// Check var.data "127.0.0.1" QHostAddress.
// Continue.
dummyStatement(&ha1);
}
......@@ -3785,7 +3786,7 @@ namespace qvariant {
//QString type = var.typeName();
var.setValue(my);
BREAK_HERE;
// Expand my my.0 my.0.value my.1 my.1.value var var.0 var.0.value var.1 var.1.value.
// Expand my my.0 my.0.value my.1 my.1.value var var.data var.data.0 var.data.0.value var.data.1 var.data.1.value.
// Check my <2 items> qvariant::MyType.
// Check my.0 QMapNode<unsigned int, QStringList>.
// Check my.0.key 1 unsigned int.
......@@ -3795,15 +3796,16 @@ namespace qvariant {
// Check my.1.key 3 unsigned int.
// Check my.1.value <1 items> QStringList.
// Check my.1.value.0 "World" QString.