Symbian: Adjust Creator to work with CODA

Reviewed-by: hjk
This commit is contained in:
Pawel Polanski
2011-01-07 15:47:22 +01:00
parent d5b2954da8
commit 051011bc37
21 changed files with 1386 additions and 273 deletions

View File

@@ -42,6 +42,9 @@
#include "qt4projectmanagerconstants.h"
#include "qtoutputformatter.h"
#include "tcftrkdevice.h"
#include "tcftrkmessage.h"
#include <symbianutils/bluetoothlistener_gui.h>
#include <symbianutils/launcher.h>
#include <symbianutils/symbiandevicemanager.h>
@@ -60,9 +63,12 @@
#include <QtCore/QDateTime>
#include <QtCore/QDir>
#include <QtNetwork/QTcpSocket>
using namespace ProjectExplorer;
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
using namespace tcftrk;
namespace {
@@ -102,7 +108,21 @@ QString pathToId(const QString &path)
return QString::fromLatin1(S60_DEVICE_RC_PREFIX) + path;
}
} // anon namespace
bool isProcessRunning(const TcfTrkCommandResult &result, const QString &processName)
{
if (result.values.size() && result.values.at(0).type() == JsonValue::Array) {
foreach(const JsonValue &threadValue, result.values.at(0).children()) {
for (int i = threadValue.children().count()-1; i >= 0; --i) { //Usually our process will be near the end of the list
const JsonValue &value(threadValue.childAt(i));
if (value.hasName("p_name") && QString::fromLatin1(value.data()).startsWith(processName, Qt::CaseInsensitive))
return true;
}
}
}
return false;
}
} // anonymous namespace
// ======== S60DeviceRunConfiguration
@@ -172,7 +192,7 @@ Qt4Target *S60DeviceRunConfiguration::qt4Target() const
}
ProjectExplorer::ToolChainType S60DeviceRunConfiguration::toolChainType(
ProjectExplorer::BuildConfiguration *configuration) const
ProjectExplorer::BuildConfiguration *configuration) const
{
if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(configuration))
return bc->toolChainType();
@@ -333,12 +353,12 @@ static inline QString localExecutableFromDevice(const QtVersion *qtv,
{
QTC_ASSERT(qtv, return QString(); )
const S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(qtv);
const S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(qtv);
QString localExecutable;
QTextStream(&localExecutable) << device.epocRoot << "/epoc32/release/"
<< symbianPlatformForToolChain(t)
<< '/' << symbianTarget << '/' << targetName
<< ".exe";
<< symbianPlatformForToolChain(t)
<< '/' << symbianTarget << '/' << targetName
<< ".exe";
return localExecutable;
}
@@ -361,11 +381,11 @@ QString S60DeviceRunConfiguration::localExecutableFileName() const
// As of 4.7.1, qmake-gcce-Raptor builds were changed to put all executables into 'armv5'
const QtVersion *qtv = qtVersion();
QTC_ASSERT(qtv, return QString(); )
return qtv->isBuildWithSymbianSbsV2() ?
localExecutableFromDevice(qtv, symbianTarget(), targetName(), ProjectExplorer::ToolChain_RVCT2_ARMV5) :
localExecutableFromDevice(qtv, symbianTarget(), targetName(), toolChain);
return qtv->isBuildWithSymbianSbsV2() ?
localExecutableFromDevice(qtv, symbianTarget(), targetName(), ProjectExplorer::ToolChain_RVCT2_ARMV5) :
localExecutableFromDevice(qtv, symbianTarget(), targetName(), toolChain);
}
break;
break;
default:
break;
}
@@ -495,10 +515,12 @@ RunConfiguration *S60DeviceRunConfigurationFactory::clone(Target *parent, RunCon
S60DeviceRunControl::S60DeviceRunControl(RunConfiguration *runConfiguration, QString mode) :
RunControl(runConfiguration, mode),
m_toolChain(ProjectExplorer::ToolChain_INVALID),
m_launcher(0)
m_tcfTrkDevice(0),
m_launcher(0),
m_state(StateUninit)
{
// connect for automatically reporting the "finished deploy" state to the progress manager
connect(this, SIGNAL(finished()), this, SLOT(reportDeployFinished()));
connect(this, SIGNAL(finished()), this, SLOT(reportLaunchFinished()));
S60DeviceRunConfiguration *s60runConfig = qobject_cast<S60DeviceRunConfiguration *>(runConfiguration);
const Qt4BuildConfiguration *activeBuildConf = s60runConfig->qt4Target()->activeBuildConfiguration();
@@ -508,6 +530,7 @@ S60DeviceRunControl::S60DeviceRunControl(RunConfiguration *runConfiguration, QSt
m_toolChain = s60runConfig->toolChainType();
m_serialPortName = activeDeployConf->serialPortName();
m_serialPortFriendlyName = SymbianUtils::SymbianDeviceManager::instance()->friendlyNameForPort(m_serialPortName);
m_executableUid = s60runConfig->executableUid();
m_targetName = s60runConfig->targetName();
m_commandLineArguments = s60runConfig->commandLineArguments();
m_qtDir = activeBuildConf->qtVersion()->versionInfo().value("QT_INSTALL_DATA");
@@ -516,13 +539,27 @@ S60DeviceRunControl::S60DeviceRunControl(RunConfiguration *runConfiguration, QSt
m_qtBinPath = qtv->versionInfo().value(QLatin1String("QT_INSTALL_BINS"));
QTC_ASSERT(!m_qtBinPath.isEmpty(), return);
m_executableFileName = s60runConfig->localExecutableFileName();
switch (activeDeployConf->communicationChannel()) {
case S60DeployConfiguration::CommunicationSerialConnection:
break;
case S60DeployConfiguration::CommunicationTcpConnection:
m_address = activeDeployConf->deviceAddress();
m_port = activeDeployConf->devicePort().toInt();
}
m_useOldTrk = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationSerialConnection;
if (debug)
qDebug() << "S60DeviceRunControl::CT" << m_targetName << ProjectExplorer::ToolChain::toolChainName(m_toolChain)
<< m_serialPortName;
<< m_serialPortName << "Use old TRK" << m_useOldTrk;
}
S60DeviceRunControl::~S60DeviceRunControl()
{
if (m_tcfTrkDevice) {
m_tcfTrkDevice->deleteLater();
m_tcfTrkDevice = 0;
}
if (m_launcher) {
m_launcher->deleteLater();
m_launcher = 0;
@@ -539,7 +576,7 @@ void S60DeviceRunControl::start()
m_launchProgress->setProgressValue(0);
m_launchProgress->reportStarted();
emit started();
if (m_serialPortName.isEmpty()) {
if (m_serialPortName.isEmpty() && m_address.isEmpty()) {
m_launchProgress->reportCanceled();
QString msg = tr("No device is connected. Please connect a device and try again.");
appendMessage(msg, NormalMessageFormat);
@@ -568,16 +605,24 @@ void S60DeviceRunControl::start()
RunControl::StopResult S60DeviceRunControl::stop()
{
if (m_launcher)
m_launcher->terminate();
if (m_useOldTrk) {
if (m_launcher)
m_launcher->terminate();
} else {
doStop();
}
return AsynchronousStop;
}
bool S60DeviceRunControl::isRunning() const
{
return m_launcher && (m_launcher->state() == trk::Launcher::Connecting
|| m_launcher->state() == trk::Launcher::Connected
|| m_launcher->state() == trk::Launcher::WaitingForTrk);
if (m_useOldTrk) {
return m_launcher && (m_launcher->state() == trk::Launcher::Connecting
|| m_launcher->state() == trk::Launcher::Connected
|| m_launcher->state() == trk::Launcher::WaitingForTrk);
} else {
return m_tcfTrkDevice && !m_tcfTrkDevice->device().isNull() && m_state >= StateConnecting;
}
}
void S60DeviceRunControl::startLaunching()
@@ -585,7 +630,7 @@ void S60DeviceRunControl::startLaunching()
QString errorMessage;
if (setupLauncher(errorMessage)) {
if (m_launchProgress)
m_launchProgress->setProgressValue(PROGRESS_MAX/2);
m_launchProgress->setProgressValue(PROGRESS_MAX/2);
} else {
if (!errorMessage.isEmpty())
appendMessage(errorMessage, ErrorMessageFormat);
@@ -598,35 +643,232 @@ bool S60DeviceRunControl::setupLauncher(QString &errorMessage)
{
connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(deviceRemoved(const SymbianUtils::SymbianDevice)),
this, SLOT(deviceRemoved(SymbianUtils::SymbianDevice)));
m_launcher = trk::Launcher::acquireFromDeviceManager(m_serialPortName, 0, &errorMessage);
if (!m_launcher)
return false;
connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished()));
connect(m_launcher, SIGNAL(canNotConnect(QString)), this, SLOT(printConnectFailed(QString)));
connect(m_launcher, SIGNAL(stateChanged(int)), this, SLOT(slotLauncherStateChanged(int)));
connect(m_launcher, SIGNAL(processStopped(uint,uint,uint,QString)),
this, SLOT(processStopped(uint,uint,uint,QString)));
if(!m_useOldTrk) { //FIXME: Remove old TRK
QTC_ASSERT(!m_tcfTrkDevice, return false);
if (!m_commandLineArguments.isEmpty())
m_launcher->setCommandLineArgs(m_commandLineArguments);
m_tcfTrkDevice = new TcfTrkDevice;
if (debug)
m_tcfTrkDevice->setVerbose(1);
const QString runFileName = QString::fromLatin1("%1:\\sys\\bin\\%2.exe").arg(m_installationDrive).arg(m_targetName);
initLauncher(runFileName, m_launcher);
const trk::PromptStartCommunicationResult src =
S60RunConfigBluetoothStarter::startCommunication(m_launcher->trkDevice(),
0, &errorMessage);
if (src != trk::PromptStartCommunicationConnected)
return false;
connect(m_tcfTrkDevice, SIGNAL(error(QString)), this, SLOT(slotError(QString)));
connect(m_tcfTrkDevice, SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString)));
connect(m_tcfTrkDevice, SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)));
connect(m_tcfTrkDevice, SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString)));
if (!m_launcher->startServer(&errorMessage)) {
errorMessage = tr("Could not connect to phone on port '%1': %2\n"
"Check if the phone is connected and App TRK is running.").arg(m_serialPortName, errorMessage);
return false;
const QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket);
m_tcfTrkDevice->setDevice(tcfTrkSocket);
tcfTrkSocket->connectToHost(m_address, m_port);
m_state = StateConnecting;
appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), NormalMessageFormat);
} else {
m_launcher = trk::Launcher::acquireFromDeviceManager(m_serialPortName, 0, &errorMessage);
if (!m_launcher)
return false;
connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished()));
connect(m_launcher, SIGNAL(canNotConnect(QString)), this, SLOT(printConnectFailed(QString)));
connect(m_launcher, SIGNAL(stateChanged(int)), this, SLOT(slotLauncherStateChanged(int)));
connect(m_launcher, SIGNAL(processStopped(uint,uint,uint,QString)),
this, SLOT(processStopped(uint,uint,uint,QString)));
if (!m_commandLineArguments.isEmpty())
m_launcher->setCommandLineArgs(m_commandLineArguments);
const QString runFileName = QString::fromLatin1("%1:\\sys\\bin\\%2.exe").arg(m_installationDrive).arg(m_targetName);
initLauncher(runFileName, m_launcher);
const trk::PromptStartCommunicationResult src =
S60RunConfigBluetoothStarter::startCommunication(m_launcher->trkDevice(),
0, &errorMessage);
if (src != trk::PromptStartCommunicationConnected)
return false;
if (!m_launcher->startServer(&errorMessage)) {
errorMessage = tr("Could not connect to phone on port '%1': %2\n"
"Check if the phone is connected and App TRK is running.").arg(m_serialPortName, errorMessage);
return false;
}
}
return true;
}
void S60DeviceRunControl::doStop()
{
if (!m_tcfTrkDevice) {
finishRunControl();
return;
}
switch (m_state) {
case StateUninit:
case StateConnecting:
case StateConnected:
finishRunControl();
break;
case StateProcessRunning:
QTC_ASSERT(!m_runningProcessId.isEmpty(), return);
m_tcfTrkDevice->sendRunControlTerminateCommand(TcfTrkCallback(),
m_runningProcessId.toAscii());
break;
}
}
void S60DeviceRunControl::slotError(const QString &error)
{
appendMessage(tr("Error: %1").arg(error), ErrorMessageFormat);
finishRunControl();
}
void S60DeviceRunControl::slotTrkLogMessage(const QString &log)
{
if (debug) {
qDebug("CODA log: %s", qPrintable(log.size()>200?log.left(200).append(QLatin1String(" ...")): log));
}
}
void S60DeviceRunControl::slotSerialPong(const QString &message)
{
if (debug)
qDebug() << "CODA serial pong:" << message;
}
void S60DeviceRunControl::slotTcftrkEvent(const TcfTrkEvent &event)
{
if (debug)
qDebug() << "CODA event:" << "Type:" << event.type() << "Message:" << event.toString();
switch (event.type()) {
case TcfTrkEvent::LocatorHello: { // Commands accepted now
m_state = StateConnected;
appendMessage(tr("Connected!"), NormalMessageFormat);
if (m_launchProgress)
m_launchProgress->setProgressValue(PROGRESS_MAX*0.80);
initCommunication();
}
break;
case TcfTrkEvent::RunControlContextRemoved:
handleContextRemoved(event);
break;
case TcfTrkEvent::RunControlContextAdded:
m_state = StateProcessRunning;
reportLaunchFinished();
handleContextAdded(event);
break;
case TcfTrkEvent::RunControlSuspended:
handleContextSuspended(event);
break;
case TcfTrkEvent::RunControlModuleLoadSuspended:
handleModuleLoadSuspended(event);
break;
default:
if (debug)
qDebug() << __FUNCTION__ << "Event not handled" << event.type();
break;
}
}
void S60DeviceRunControl::initCommunication()
{
m_tcfTrkDevice->sendSettingsEnableLogCommand();
m_tcfTrkDevice->sendLoggingAddListenerCommand(TcfTrkCallback(this, &S60DeviceRunControl::handleAddListener));
}
void S60DeviceRunControl::handleContextRemoved(const TcfTrkEvent &event)
{
QVector<QByteArray> &removedItems( static_cast<const TcfTrkRunControlContextRemovedEvent &>(event).ids());
if (!m_runningProcessId.isEmpty()
&& removedItems.contains(m_runningProcessId.toAscii())) {
appendMessage(tr("Process has finished."), NormalMessageFormat);
finishRunControl();
}
}
void S60DeviceRunControl::handleContextAdded(const TcfTrkEvent &event)
{
typedef TcfTrkRunControlContextAddedEvent TcfAddedEvent;
const TcfAddedEvent &me = static_cast<const TcfAddedEvent &>(event);
foreach (const RunControlContext &context, me.contexts()) {
if (context.parentId == "root") //is the created context a process
m_runningProcessId = QLatin1String(context.id);
}
}
void S60DeviceRunControl::handleContextSuspended(const TcfTrkEvent &event)
{
typedef TcfTrkRunControlContextSuspendedEvent TcfSuspendEvent;
const TcfSuspendEvent &me = static_cast<const TcfSuspendEvent &>(event);
switch (me.reason()) {
case TcfSuspendEvent::Crash:
appendMessage(tr("Process has crashed: %1").arg(QString::fromLatin1(me.message())), ErrorMessageFormat);
m_tcfTrkDevice->sendRunControlResumeCommand(TcfTrkCallback(), me.id()); //TODO: Should I resume automaticly
break;
default:
if (debug)
qDebug() << "Context suspend not handled:" << "Reason:" << me.reason() << "Message:" << me.message();
break;
}
}
void S60DeviceRunControl::handleModuleLoadSuspended(const TcfTrkEvent &event)
{
// Debug mode start: Continue:
typedef TcfTrkRunControlModuleLoadContextSuspendedEvent TcfModuleLoadSuspendedEvent;
const TcfModuleLoadSuspendedEvent &me = static_cast<const TcfModuleLoadSuspendedEvent &>(event);
if (me.info().requireResume)
m_tcfTrkDevice->sendRunControlResumeCommand(TcfTrkCallback(), me.id());
}
void S60DeviceRunControl::handleAddListener(const TcfTrkCommandResult &result)
{
if (debug)
qDebug() << __FUNCTION__ <<"Add log listener" << result.toString();
m_tcfTrkDevice->sendSymbianOsDataGetThreadsCommand(TcfTrkCallback(this, &S60DeviceRunControl::handleGetThreads));
}
void S60DeviceRunControl::handleGetThreads(const TcfTrkCommandResult &result)
{
if (isProcessRunning(result, m_targetName)) {
appendMessage(tr("The process is already running on the device. Please first close it."), ErrorMessageFormat);
finishRunControl();
} else {
if (m_launchProgress)
m_launchProgress->setProgressValue(PROGRESS_MAX*0.90);
const QString runFileName = QString::fromLatin1("%1.exe").arg(m_targetName);
m_tcfTrkDevice->sendProcessStartCommand(TcfTrkCallback(this, &S60DeviceRunControl::handleCreateProcess),
runFileName, m_executableUid, m_commandLineArguments.split(" "), QString(), true);
appendMessage(tr("Launching: %1").arg(runFileName), NormalMessageFormat);
}
}
void S60DeviceRunControl::handleCreateProcess(const TcfTrkCommandResult &result)
{
const bool ok = result.type == TcfTrkCommandResult::SuccessReply;
if (ok) {
if (m_launchProgress)
m_launchProgress->setProgressValue(PROGRESS_MAX);
appendMessage(tr("Launched!"), NormalMessageFormat);
} else {
appendMessage(tr("Launch failed: %1").arg(result.toString()), ErrorMessageFormat);
finishRunControl();
}
}
void S60DeviceRunControl::finishRunControl()
{
m_runningProcessId.clear();
if (m_tcfTrkDevice)
m_tcfTrkDevice->deleteLater();
m_tcfTrkDevice = 0;
m_state = StateUninit;
handleRunFinished();
}
//////// Launcher code - to be removed
void S60DeviceRunControl::printConnectFailed(const QString &errorMessage)
{
appendMessage(tr("Could not connect to App TRK on device: %1. Restarting App TRK might help.").arg(errorMessage),
@@ -638,10 +880,10 @@ void S60DeviceRunControl::launcherFinished()
trk::Launcher::releaseToDeviceManager(m_launcher);
m_launcher->deleteLater();
m_launcher = 0;
handleLauncherFinished();
handleRunFinished();
}
void S60DeviceRunControl::reportDeployFinished()
void S60DeviceRunControl::reportLaunchFinished()
{
if (m_launchProgress) {
m_launchProgress->reportFinished();
@@ -672,7 +914,7 @@ void S60DeviceRunControl::slotLauncherStateChanged(int s)
{
if (s == trk::Launcher::WaitingForTrk) {
QMessageBox *mb = S60DeviceRunControl::createTrkWaitingMessageBox(m_launcher->trkServerName(),
Core::ICore::instance()->mainWindow());
Core::ICore::instance()->mainWindow());
connect(m_launcher, SIGNAL(stateChanged(int)), mb, SLOT(close()));
connect(mb, SIGNAL(finished(int)), this, SLOT(slotWaitingForTrkClosed()));
mb->open();
@@ -710,29 +952,16 @@ void S60DeviceRunControl::deviceRemoved(const SymbianUtils::SymbianDevice &d)
}
}
bool S60DeviceRunControl::checkConfiguration(QString * /* errorMessage */,
QString * /* settingsCategory */,
QString * /* settingsPage */) const
{
return true;
}
void S60DeviceRunControl::initLauncher(const QString &executable, trk::Launcher *launcher)
{
connect(launcher, SIGNAL(startingApplication()), this, SLOT(printStartingNotice()));
connect(launcher, SIGNAL(applicationRunning(uint)), this, SLOT(applicationRunNotice(uint)));
connect(launcher, SIGNAL(canNotRun(QString)), this, SLOT(applicationRunFailedNotice(QString)));
connect(launcher, SIGNAL(applicationOutputReceived(QString)), this, SLOT(printApplicationOutput(QString)));
launcher->addStartupActions(trk::Launcher::ActionRun);
launcher->setFileName(executable);
connect(launcher, SIGNAL(startingApplication()), this, SLOT(printStartingNotice()));
connect(launcher, SIGNAL(applicationRunning(uint)), this, SLOT(applicationRunNotice(uint)));
connect(launcher, SIGNAL(canNotRun(QString)), this, SLOT(applicationRunFailedNotice(QString)));
connect(launcher, SIGNAL(applicationOutputReceived(QString)), this, SLOT(printApplicationOutput(QString)));
launcher->addStartupActions(trk::Launcher::ActionRun);
launcher->setFileName(executable);
}
void S60DeviceRunControl::handleLauncherFinished()
{
emit finished();
appendMessage(tr("Finished."), NormalMessageFormat);
}
void S60DeviceRunControl::printStartingNotice()
{
appendMessage(tr("Starting application..."), NormalMessageFormat);
@@ -750,6 +979,21 @@ void S60DeviceRunControl::applicationRunFailedNotice(const QString &errorMessage
appendMessage(tr("Could not start application: %1").arg(errorMessage), NormalMessageFormat);
}
// End of Launcher code - to be removed
bool S60DeviceRunControl::checkConfiguration(QString * /* errorMessage */,
QString * /* settingsCategory */,
QString * /* settingsPage */) const
{
return true;
}
void S60DeviceRunControl::handleRunFinished()
{
emit finished();
appendMessage(tr("Finished."), NormalMessageFormat);
}
// ======== S60DeviceDebugRunControl
// Return symbol file which should co-exist with the executable.
@@ -790,7 +1034,13 @@ static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceR
sp.executable = debugFileName;
sp.executableUid = rc->executableUid();
sp.enabledEngines = Debugger::GdbEngineType;
sp.serverAddress = activeDeployConf->deviceAddress();
sp.serverPort = activeDeployConf->devicePort().toInt();
//FIXME: there should be only one... trkAdapter
sp.communicationChannel = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationSerialConnection?
Debugger::DebuggerStartParameters::CommunicationChannelUsb:
Debugger::DebuggerStartParameters::CommunicationChannelTcpIp;
QTC_ASSERT(sp.executableUid, return sp);
// Prefer the '*.sym' file over the '.exe', which should exist at the same