forked from qt-creator/qt-creator
349 lines
10 KiB
C++
349 lines
10 KiB
C++
|
|
/****************************************************************************
|
||
|
|
**
|
||
|
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||
|
|
** Contact: http://www.qt-project.org/legal
|
||
|
|
**
|
||
|
|
** This file is part of Qt Creator.
|
||
|
|
**
|
||
|
|
** Commercial License Usage
|
||
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||
|
|
** accordance with the commercial license agreement provided with the
|
||
|
|
** Software or, alternatively, in accordance with the terms contained in
|
||
|
|
** a written agreement between you and Digia. For licensing terms and
|
||
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
||
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
||
|
|
**
|
||
|
|
** GNU Lesser General Public License Usage
|
||
|
|
** Alternatively, 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, Digia gives you certain additional
|
||
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||
|
|
**
|
||
|
|
****************************************************************************/
|
||
|
|
|
||
|
|
#include "qmltoolsclient.h"
|
||
|
|
#include <QStringList>
|
||
|
|
|
||
|
|
//INSPECTOR SERVICE PROTOCOL
|
||
|
|
// <HEADER><COMMAND><DATA>
|
||
|
|
// <HEADER> : <type{request, response, event}><requestId/eventId>[<response_success_bool>]
|
||
|
|
// <COMMAND> : {"enable", "disable", "select", "reload", "setAnimationSpeed",
|
||
|
|
// "showAppOnTop", "createObject", "destroyObject", "moveObject",
|
||
|
|
// "clearCache"}
|
||
|
|
// <DATA> : select: <debugIds_int_list>
|
||
|
|
// reload: <hash<changed_filename_string, filecontents_bytearray>>
|
||
|
|
// setAnimationSpeed: <speed_real>
|
||
|
|
// showAppOnTop: <set_bool>
|
||
|
|
// createObject: <qml_string><parentId_int><imports_string_list><filename_string>
|
||
|
|
// destroyObject: <debugId_int>
|
||
|
|
// moveObject: <debugId_int><newParentId_int>
|
||
|
|
// clearCache: void
|
||
|
|
|
||
|
|
const char REQUEST[] = "request";
|
||
|
|
const char RESPONSE[] = "response";
|
||
|
|
const char EVENT[] = "event";
|
||
|
|
const char ENABLE[] = "enable";
|
||
|
|
const char DISABLE[] = "disable";
|
||
|
|
const char SELECT[] = "select";
|
||
|
|
const char RELOAD[] = "reload";
|
||
|
|
const char SET_ANIMATION_SPEED[] = "setAnimationSpeed";
|
||
|
|
const char SHOW_APP_ON_TOP[] = "showAppOnTop";
|
||
|
|
const char CREATE_OBJECT[] = "createObject";
|
||
|
|
const char DESTROY_OBJECT[] = "destroyObject";
|
||
|
|
const char MOVE_OBJECT[] = "moveObject";
|
||
|
|
const char CLEAR_CACHE[] = "clearCache";
|
||
|
|
|
||
|
|
namespace QmlDebug {
|
||
|
|
|
||
|
|
QmlToolsClient::QmlToolsClient(QmlDebugConnection *client)
|
||
|
|
: BaseToolsClient(client, QLatin1String("QmlInspector")),
|
||
|
|
m_connection(client),
|
||
|
|
m_requestId(0),
|
||
|
|
m_reloadQueryId(-1),
|
||
|
|
m_slowDownFactor(1),
|
||
|
|
m_destroyObjectQueryId(-1)
|
||
|
|
{
|
||
|
|
setObjectName(name());
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::messageReceived(const QByteArray &message)
|
||
|
|
{
|
||
|
|
QDataStream ds(message);
|
||
|
|
|
||
|
|
QByteArray type;
|
||
|
|
int requestId;
|
||
|
|
ds >> type >> requestId;
|
||
|
|
|
||
|
|
if (type == QByteArray(RESPONSE)) {
|
||
|
|
bool success = false;
|
||
|
|
ds >> success;
|
||
|
|
|
||
|
|
if ((m_reloadQueryId != -1) && (m_reloadQueryId == requestId) && success)
|
||
|
|
emit reloaded();
|
||
|
|
|
||
|
|
if ((m_destroyObjectQueryId != -1) && (m_destroyObjectQueryId == requestId)
|
||
|
|
&& success && !ds.atEnd()) {
|
||
|
|
int objectDebugId;
|
||
|
|
ds >> objectDebugId;
|
||
|
|
emit destroyedObject(objectDebugId);
|
||
|
|
}
|
||
|
|
|
||
|
|
log(LogReceive, type, QString(QLatin1String("requestId: %1 success: %2"))
|
||
|
|
.arg(QString::number(requestId)).arg(QString::number(success)));
|
||
|
|
} else if (type == QByteArray(EVENT)) {
|
||
|
|
QByteArray event;
|
||
|
|
ds >> event;
|
||
|
|
if (event == QByteArray(SELECT)) {
|
||
|
|
m_currentDebugIds.clear();
|
||
|
|
QList<int> debugIds;
|
||
|
|
ds >> debugIds;
|
||
|
|
|
||
|
|
QStringList debugIdStrings;
|
||
|
|
foreach (int debugId, debugIds) {
|
||
|
|
if (debugId != -1) {
|
||
|
|
m_currentDebugIds << debugId;
|
||
|
|
debugIdStrings << QString::number(debugId);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
log(LogReceive, type + ':' + event,
|
||
|
|
QString::fromLatin1("[%1]").arg(debugIdStrings.join(QLatin1String(","))));
|
||
|
|
emit currentObjectsChanged(m_currentDebugIds);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
log(LogReceive, type, QLatin1String("Warning: Not handling message"));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
QList<int> QmlToolsClient::currentObjects() const
|
||
|
|
{
|
||
|
|
return m_currentDebugIds;
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::setCurrentObjects(const QList<int> &debugIds)
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (debugIds == m_currentDebugIds)
|
||
|
|
return;
|
||
|
|
|
||
|
|
m_currentDebugIds = debugIds;
|
||
|
|
|
||
|
|
QByteArray message;
|
||
|
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||
|
|
ds << QByteArray(REQUEST) << m_requestId++
|
||
|
|
<< QByteArray(SELECT) << m_currentDebugIds;
|
||
|
|
|
||
|
|
log(LogSend, SELECT, QString::fromLatin1("%1 [list of ids]").arg(debugIds.length()));
|
||
|
|
|
||
|
|
sendMessage(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::setObjectIdList(
|
||
|
|
const QList<ObjectReference> &/*objectRoots*/)
|
||
|
|
{
|
||
|
|
//NOT IMPLEMENTED
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::clearComponentCache()
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
|
||
|
|
QByteArray message;
|
||
|
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||
|
|
ds << QByteArray(REQUEST) << m_requestId++
|
||
|
|
<< QByteArray(CLEAR_CACHE);
|
||
|
|
|
||
|
|
log(LogSend, CLEAR_CACHE);
|
||
|
|
|
||
|
|
sendMessage(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::reload(const QHash<QString, QByteArray> &changesHash)
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
|
||
|
|
m_reloadQueryId = m_requestId;
|
||
|
|
|
||
|
|
QByteArray message;
|
||
|
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||
|
|
ds << QByteArray(REQUEST) << m_requestId++
|
||
|
|
<< QByteArray(RELOAD) << changesHash;
|
||
|
|
|
||
|
|
log(LogSend, RELOAD);
|
||
|
|
|
||
|
|
sendMessage(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::setDesignModeBehavior(bool inDesignMode)
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
|
||
|
|
QByteArray message;
|
||
|
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||
|
|
ds << QByteArray(REQUEST) << m_requestId++;
|
||
|
|
if (inDesignMode)
|
||
|
|
ds << QByteArray(ENABLE);
|
||
|
|
else
|
||
|
|
ds << QByteArray(DISABLE);
|
||
|
|
|
||
|
|
log(LogSend, ENABLE, QLatin1String(inDesignMode ? "true" : "false"));
|
||
|
|
|
||
|
|
sendMessage(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::setAnimationSpeed(qreal slowDownFactor)
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
|
||
|
|
QByteArray message;
|
||
|
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||
|
|
ds << QByteArray(REQUEST) << m_requestId++
|
||
|
|
<< QByteArray(SET_ANIMATION_SPEED) << slowDownFactor;
|
||
|
|
|
||
|
|
log(LogSend, SET_ANIMATION_SPEED, QString::number(slowDownFactor));
|
||
|
|
|
||
|
|
sendMessage(message);
|
||
|
|
//Cache non-zero values
|
||
|
|
if (slowDownFactor)
|
||
|
|
m_slowDownFactor = slowDownFactor;
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::setAnimationPaused(bool paused)
|
||
|
|
{
|
||
|
|
if (paused)
|
||
|
|
setAnimationSpeed(0);
|
||
|
|
else
|
||
|
|
setAnimationSpeed(m_slowDownFactor);
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::changeToSelectTool()
|
||
|
|
{
|
||
|
|
// NOT IMPLEMENTED
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::changeToSelectMarqueeTool()
|
||
|
|
{
|
||
|
|
// NOT IMPLEMENTED
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::changeToZoomTool()
|
||
|
|
{
|
||
|
|
// NOT IMPLEMENTED
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::showAppOnTop(bool showOnTop)
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
|
||
|
|
QByteArray message;
|
||
|
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||
|
|
ds << QByteArray(REQUEST) << m_requestId++
|
||
|
|
<< QByteArray(SHOW_APP_ON_TOP) << showOnTop;
|
||
|
|
|
||
|
|
log(LogSend, SHOW_APP_ON_TOP, QLatin1String(showOnTop ? "true" : "false"));
|
||
|
|
|
||
|
|
sendMessage(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::createQmlObject(const QString &qmlText,
|
||
|
|
int parentDebugId,
|
||
|
|
const QStringList &imports,
|
||
|
|
const QString &filename, int order)
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
|
||
|
|
QByteArray message;
|
||
|
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||
|
|
ds << QByteArray(REQUEST) << m_requestId++
|
||
|
|
<< QByteArray(CREATE_OBJECT)
|
||
|
|
<< qmlText
|
||
|
|
<< parentDebugId
|
||
|
|
<< imports
|
||
|
|
<< filename
|
||
|
|
<< order;
|
||
|
|
|
||
|
|
log(LogSend, CREATE_OBJECT, QString::fromLatin1("%1 %2 [%3] %4").arg(qmlText,
|
||
|
|
QString::number(parentDebugId),
|
||
|
|
imports.join(QLatin1String(",")), filename));
|
||
|
|
|
||
|
|
sendMessage(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::destroyQmlObject(int debugId)
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
QByteArray message;
|
||
|
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||
|
|
m_destroyObjectQueryId = m_requestId;
|
||
|
|
ds << QByteArray(REQUEST) << m_requestId++
|
||
|
|
<< QByteArray(DESTROY_OBJECT) << debugId;
|
||
|
|
|
||
|
|
log(LogSend, DESTROY_OBJECT, QString::number(debugId));
|
||
|
|
|
||
|
|
sendMessage(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::reparentQmlObject(int debugId, int newParent)
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
QByteArray message;
|
||
|
|
QDataStream ds(&message, QIODevice::WriteOnly);
|
||
|
|
ds << QByteArray(REQUEST) << m_requestId++
|
||
|
|
<< QByteArray(MOVE_OBJECT) << debugId << newParent;
|
||
|
|
|
||
|
|
log(LogSend, MOVE_OBJECT, QString::fromLatin1("%1 %2").arg(QString::number(debugId),
|
||
|
|
QString::number(newParent)));
|
||
|
|
|
||
|
|
sendMessage(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void QmlToolsClient::applyChangesToQmlFile()
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
|
||
|
|
// TODO
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::applyChangesFromQmlFile()
|
||
|
|
{
|
||
|
|
if (!m_connection || !m_connection->isConnected())
|
||
|
|
return;
|
||
|
|
|
||
|
|
// TODO
|
||
|
|
}
|
||
|
|
|
||
|
|
void QmlToolsClient::log(LogDirection direction,
|
||
|
|
const QByteArray &message,
|
||
|
|
const QString &extra)
|
||
|
|
{
|
||
|
|
QString msg;
|
||
|
|
if (direction == LogSend)
|
||
|
|
msg += QLatin1String("sending ");
|
||
|
|
else
|
||
|
|
msg += QLatin1String("receiving ");
|
||
|
|
|
||
|
|
msg += QLatin1String(message);
|
||
|
|
msg += QLatin1Char(' ');
|
||
|
|
msg += extra;
|
||
|
|
emit logActivity(name(), msg);
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace QmlDebug
|