diff --git a/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp b/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp index d5f33ab4b59..14823fbb319 100644 --- a/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp +++ b/src/libs/qmljsdebugclient/qdeclarativedebugclient.cpp @@ -45,12 +45,14 @@ #include #include +#include namespace QmlJsDebugClient { const int protocolVersion = 1; const QString serverId = QLatin1String("QDeclarativeDebugServer"); const QString clientId = QLatin1String("QDeclarativeDebugClient"); +static const uchar KQmlOstProtocolId = 0x94; class QDeclarativeDebugClientPrivate { @@ -69,20 +71,23 @@ public: QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c); QDeclarativeDebugConnection *q; QPacketProtocol *protocol; + QIODevice *device; // Currently either a QTcpSocket or a SymbianUtils::OstChannel bool gotHello; QStringList serverPlugins; QHash plugins; void advertisePlugins(); + void connectDeviceSignals(); public Q_SLOTS: void connected(); void readyRead(); + void deviceAboutToClose(); }; QDeclarativeDebugConnectionPrivate::QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c) -: QObject(c), q(c), protocol(0), gotHello(false) +: QObject(c), q(c), protocol(0), gotHello(false), device(0) { protocol = new QPacketProtocol(q, this); QObject::connect(c, SIGNAL(connected()), this, SLOT(connected())); @@ -190,8 +195,15 @@ void QDeclarativeDebugConnectionPrivate::readyRead() } } +void QDeclarativeDebugConnectionPrivate::deviceAboutToClose() +{ + // This is nasty syntax but we want to emit our own aboutToClose signal (by calling QIODevice::close()) + // without calling the underlying device close fn as that would cause an infinite loop + q->QIODevice::close(); +} + QDeclarativeDebugConnection::QDeclarativeDebugConnection(QObject *parent) -: QTcpSocket(parent), d(new QDeclarativeDebugConnectionPrivate(this)) +: QIODevice(parent), d(new QDeclarativeDebugConnectionPrivate(this)) { } @@ -206,9 +218,112 @@ QDeclarativeDebugConnection::~QDeclarativeDebugConnection() bool QDeclarativeDebugConnection::isConnected() const { - return state() == ConnectedState; + return state() == QAbstractSocket::ConnectedState; } +qint64 QDeclarativeDebugConnection::readData(char *data, qint64 maxSize) +{ + return d->device->read(data, maxSize); +} + +qint64 QDeclarativeDebugConnection::writeData(const char *data, qint64 maxSize) +{ + return d->device->write(data, maxSize); +} + +qint64 QDeclarativeDebugConnection::bytesAvailable() const +{ + return d->device->bytesAvailable(); +} + +bool QDeclarativeDebugConnection::isSequential() const +{ + return true; +} + +void QDeclarativeDebugConnection::close() +{ + if (isOpen()) { + QIODevice::close(); + d->device->close(); + emit stateChanged(QAbstractSocket::UnconnectedState); + } +} + +// For ease of refactoring we use QAbstractSocket's states even if we're actually using a OstChannel underneath +// since serial ports have a subset of the socket states afaics +QAbstractSocket::SocketState QDeclarativeDebugConnection::state() const +{ + QAbstractSocket *socket = qobject_cast(d->device); + if (socket) + return socket->state(); + + SymbianUtils::OstChannel *ost = qobject_cast(d->device); + if (ost) { + //TODO we need some handshaking here + /* + if (ost->hasReceivedData()) + return QAbstractSocket::ConnectedState; + else if (ost->isOpen()) + return QAbstractSocket::ConnectingState; + */ + if (ost->isOpen()) return QAbstractSocket::ConnectedState; + } + + return QAbstractSocket::UnconnectedState; +} + +void QDeclarativeDebugConnection::flush() +{ + QAbstractSocket *socket = qobject_cast(d->device); + if (socket) { + socket->flush(); + return; + } + + SymbianUtils::OstChannel *ost = qobject_cast(d->device); + if (ost) { + ost->flush(); + return; + } +} + +void QDeclarativeDebugConnection::connectToHost(const QString &hostName, quint16 port) +{ + QTcpSocket *socket = new QTcpSocket(d); + d->device = socket; + d->connectDeviceSignals(); + connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SIGNAL(stateChanged(QAbstractSocket::SocketState))); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(error(QAbstractSocket::SocketError))); + connect(socket, SIGNAL(connected()), this, SIGNAL(connected())); + socket->connectToHost(hostName, port); + QIODevice::open(ReadWrite | Unbuffered); +} + +void QDeclarativeDebugConnection::connectToOst(const QString &port) +{ + SymbianUtils::OstChannel *ost = SymbianUtils::SymbianDeviceManager::instance()->getOstChannel(port, KQmlOstProtocolId); + if (ost) { + ost->setParent(d); + d->device = ost; + d->connectDeviceSignals(); + QIODevice::open(ReadWrite | Unbuffered); + emit stateChanged(QAbstractSocket::ConnectedState); + emit connected(); + } else { + emit error(QAbstractSocket::HostNotFoundError); + } +} + +void QDeclarativeDebugConnectionPrivate::connectDeviceSignals() +{ + connect(device, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64))); + connect(device, SIGNAL(readyRead()), q, SIGNAL(readyRead())); + connect(device, SIGNAL(aboutToClose()), this, SLOT(deviceAboutToClose())); +} + +// + QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate() : connection(0) { diff --git a/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h b/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h index 665912c60bb..4ff3e4e0c20 100644 --- a/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h +++ b/src/libs/qmljsdebugclient/qdeclarativedebugclient_p.h @@ -49,7 +49,7 @@ QT_BEGIN_HEADER namespace QmlJsDebugClient { class QDeclarativeDebugConnectionPrivate; -class QDeclarativeDebugConnection : public QTcpSocket +class QDeclarativeDebugConnection : public QIODevice { Q_OBJECT Q_DISABLE_COPY(QDeclarativeDebugConnection) @@ -57,7 +57,25 @@ public: QDeclarativeDebugConnection(QObject * = 0); ~QDeclarativeDebugConnection(); + void connectToHost(const QString &hostName, quint16 port); + void connectToOst(const QString &port); + + qint64 bytesAvailable() const; bool isConnected() const; + QAbstractSocket::SocketState state() const; + void flush(); + bool isSequential() const; + void close(); + +signals: + void connected(); + void stateChanged(QAbstractSocket::SocketState socketState); + void error(QAbstractSocket::SocketError socketError); + +private: + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + private: QDeclarativeDebugConnectionPrivate *d; friend class QDeclarativeDebugClient; diff --git a/src/plugins/debugger/qml/qmladapter.cpp b/src/plugins/debugger/qml/qmladapter.cpp index a80eacd22a8..0980f2cb87b 100644 --- a/src/plugins/debugger/qml/qmladapter.cpp +++ b/src/plugins/debugger/qml/qmladapter.cpp @@ -100,7 +100,7 @@ void QmlAdapter::closeConnection() d->m_connectionTimer.stop(); } else { if (d->m_conn) { - d->m_conn->disconnectFromHost(); + d->m_conn->close(); } } } @@ -127,11 +127,23 @@ void QmlAdapter::connectToViewer() || (d->m_conn && d->m_conn->state() != QAbstractSocket::UnconnectedState)) return; - QString address = d->m_engine.data()->startParameters().qmlServerAddress; - quint16 port = d->m_engine.data()->startParameters().qmlServerPort; - showConnectionStatusMessage( - tr("Connect to debug server %1:%2").arg(address).arg(QString::number(port))); - d->m_conn->connectToHost(address, port); + const DebuggerStartParameters ¶meters = d->m_engine.data()->startParameters(); + if (parameters.communicationChannel == DebuggerStartParameters::CommunicationChannelUsb) { + if (parameters.debugClient == DebuggerStartParameters::DebugClientTrk) { + d->m_connectionTimer.stop(); + showConnectionErrorMessage(tr("QML debugging is not supported when using TRK!")); + emit connectionStartupFailed(); + return; + } + const QString &port = parameters.remoteChannel; + showConnectionStatusMessage(tr("Connecting to debug server on %1").arg(port)); + d->m_conn->connectToOst(port); + } else { + const QString &address = parameters.qmlServerAddress; + quint16 port = parameters.qmlServerPort; + showConnectionStatusMessage(tr("Connecting to debug server %1:%2").arg(address).arg(QString::number(port))); + d->m_conn->connectToHost(address, port); + } } void QmlAdapter::sendMessage(const QByteArray &msg) @@ -147,7 +159,7 @@ void QmlAdapter::sendMessage(const QByteArray &msg) void QmlAdapter::connectionErrorOccurred(QAbstractSocket::SocketError socketError) { showConnectionStatusMessage(tr("Error: (%1) %2", "%1=error code, %2=error message") - .arg(d->m_conn->error()).arg(d->m_conn->errorString())); + .arg(socketError).arg(d->m_conn->errorString())); // this is only an error if we are already connected and something goes wrong. if (isConnected()) diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index be5f3d4d3ed..78e519a2aea 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -465,6 +465,13 @@ static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceR sp.serverAddress = activeDeployConf->deviceAddress(); sp.serverPort = activeDeployConf->devicePort().toInt(); sp.displayName = rc->displayName(); + sp.qmlServerPort = rc->qmlDebugServerPort(); + // TODO - is this the correct place to put this? + if (rc->useQmlDebugger()) { + if (sp.processArgs.length()) + sp.processArgs.prepend(" "); + sp.processArgs.prepend(QString("-qmljsdebugger=port:%1").arg(sp.qmlServerPort)); + } sp.communicationChannel = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationCodaTcpConnection? Debugger::DebuggerStartParameters::CommunicationChannelTcpIp: